Replace Mini/QR Plus copy and system prompt with Transfer file-sharing context, suggestions, and dashboard metrics. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -26,7 +26,7 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
$balanceMinor = $this->billing->balanceMinor($publicId);
|
||||
$ledger = $this->billing->serviceLedger($publicId, config('billing.service', 'mini'));
|
||||
$ledger = $this->billing->serviceLedger($publicId, config('billing.service', 'transfer'));
|
||||
|
||||
return [$balanceMinor, $ledger];
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
namespace App\Http\Controllers\Qr;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\QrCode;
|
||||
use App\Models\Transfer;
|
||||
use App\Models\TransferDownloadEvent;
|
||||
use App\Services\Afia\AfiaService;
|
||||
use App\Services\Billing\BillingClient;
|
||||
use App\Support\Qr\QrTypeCatalog;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -45,19 +45,32 @@ class AfiaController extends Controller
|
||||
return ['signed_in' => 'no'];
|
||||
}
|
||||
|
||||
$types = QrTypeCatalog::eventTypes();
|
||||
$codes = $account->qrCodes()->whereIn('type', $types);
|
||||
$active = Transfer::query()
|
||||
->where('user_id', $account->id)
|
||||
->where('status', Transfer::STATUS_ACTIVE);
|
||||
|
||||
$storageBytes = (int) (clone $active)->sum('storage_bytes');
|
||||
$storageGb = round($storageBytes / (1024 * 1024 * 1024), 2);
|
||||
|
||||
$transferIds = Transfer::query()
|
||||
->where('user_id', $account->id)
|
||||
->pluck('id');
|
||||
|
||||
$ctx = [
|
||||
'signed_in' => 'yes',
|
||||
'qr_codes_total' => (clone $codes)->count(),
|
||||
'qr_codes_active' => (clone $codes)->where('is_active', true)->count(),
|
||||
'scans_total' => (int) (clone $codes)->sum('scans_total'),
|
||||
'top_code_type' => (clone $codes)
|
||||
->selectRaw('type, count(*) as total')
|
||||
->groupBy('type')
|
||||
->orderByDesc('total')
|
||||
->value('type') ?: 'none yet',
|
||||
'active_transfers' => (clone $active)->count(),
|
||||
'storage_gb' => $storageGb,
|
||||
'downloads_30d' => TransferDownloadEvent::query()
|
||||
->whereIn('transfer_id', $transferIds)
|
||||
->where('downloaded_at', '>=', now()->subDays(30))
|
||||
->count(),
|
||||
'expiring_within_7_days' => Transfer::query()
|
||||
->where('user_id', $account->id)
|
||||
->where('status', Transfer::STATUS_ACTIVE)
|
||||
->whereNotNull('expires_at')
|
||||
->whereBetween('expires_at', [now(), now()->addDays(7)])
|
||||
->count(),
|
||||
'storage_price_per_gb_month_ghs' => number_format((float) config('transfer.price_per_gb_month', 1.0), 2),
|
||||
];
|
||||
|
||||
if ($account->public_id) {
|
||||
@@ -67,18 +80,21 @@ class AfiaController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$recent = $account->qrCodes()
|
||||
->whereIn('type', $types)
|
||||
->latest('updated_at')
|
||||
$recent = Transfer::query()
|
||||
->where('user_id', $account->id)
|
||||
->where('status', Transfer::STATUS_ACTIVE)
|
||||
->with('qrCode:id,short_code')
|
||||
->latest()
|
||||
->limit(3)
|
||||
->get(['type', 'label', 'short_code', 'scans_total']);
|
||||
->get(['id', 'title', 'qr_code_id', 'download_count', 'expires_at']);
|
||||
|
||||
if ($recent->isNotEmpty()) {
|
||||
$ctx['recent_codes'] = $recent->map(fn (QrCode $code): string => sprintf(
|
||||
'%s (%s, %d scans)',
|
||||
$code->label ?: $code->short_code,
|
||||
QrTypeCatalog::label($code->type),
|
||||
$code->scans_total,
|
||||
$ctx['recent_transfers'] = $recent->map(fn (Transfer $transfer): string => sprintf(
|
||||
'%s (%s, %d downloads%s)',
|
||||
$transfer->title,
|
||||
$transfer->qrCode?->short_code ?? 'no QR',
|
||||
$transfer->download_count,
|
||||
$transfer->expires_at ? ', expires '.$transfer->expires_at->toDateString() : '',
|
||||
))->implode('; ');
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Http;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Afia — Ladill in-app AI assistant scoped to a product (QR Plus).
|
||||
* Afia — Ladill in-app AI assistant scoped to a product.
|
||||
*/
|
||||
class AfiaService
|
||||
{
|
||||
@@ -88,36 +88,40 @@ class AfiaService
|
||||
{
|
||||
$ctx = collect($context)->map(fn ($v, $k) => "- {$k}: {$v}")->implode("\n");
|
||||
|
||||
return match ((string) config('afia.product', 'qr')) {
|
||||
'qr' => $this->qrSystemPrompt($ctx),
|
||||
default => $this->qrSystemPrompt($ctx),
|
||||
return match ((string) config('afia.product', 'transfer')) {
|
||||
'transfer' => $this->transferSystemPrompt($ctx),
|
||||
default => $this->transferSystemPrompt($ctx),
|
||||
};
|
||||
}
|
||||
|
||||
private function qrSystemPrompt(string $ctx): string
|
||||
private function transferSystemPrompt(string $ctx): string
|
||||
{
|
||||
$pricePerGb = number_format((float) config('transfer.price_per_gb_month', 1.0), 2);
|
||||
|
||||
return <<<PROMPT
|
||||
You are Afia, the assistant inside Ladill QR Plus (qrplus.ladill.com).
|
||||
Help users create and manage dynamic QR codes, understand scans and billing, and print codes that work reliably.
|
||||
You are Afia, the assistant inside Ladill Transfer (transfer.ladill.com).
|
||||
Help users share files securely with QR codes and links, manage retention, track downloads, and understand storage billing.
|
||||
Be concise, friendly, and actionable: short numbered steps and name the screen or section to use.
|
||||
|
||||
What Ladill QR Plus does and where things live:
|
||||
- Overview (Dashboard): recent codes, active code count, scans in the last 30 days, wallet balance.
|
||||
- My Codes: list, create, and edit QR codes. Types: Link (URL), PDF, List of Links, Business profile, WiFi, App download.
|
||||
- Creating a code: pick a type, set content, customize style (colors, logo, frame), then download PNG/SVG/PDF.
|
||||
- Dynamic codes: destination can change after printing — the printed QR always points to ladill.com/q/{code}.
|
||||
- Business QR: name, tagline, contact, hours, logo, cover, social links — shown as a mobile landing page.
|
||||
- WiFi QR: guests scan to join; network name and password are encoded in the code.
|
||||
- PDF QR: hosts a PDF with optional download button on the viewer.
|
||||
- Billing: each new code debits the Ladill wallet (account portal → Wallet). Top up at account.ladill.com/wallet.
|
||||
- Team: invite teammates to manage codes together (sidebar → Team).
|
||||
- Developers: API tokens for programmatic code creation (sidebar → Developers).
|
||||
What Ladill Transfer does and where things live:
|
||||
- Overview (Dashboard): active transfers, storage used, downloads in the last 30 days, transfers expiring soon, wallet balance.
|
||||
- Transfers: list all file shares; create a new transfer (upload one or more files, title, optional message, retention period, optional password).
|
||||
- After creating a transfer: users get a share link and downloadable QR code; recipients scan ladill.com/q/{code} or open the link.
|
||||
- Files: browse all stored files across transfers with sizes and download counts.
|
||||
- Analytics: download trends, top transfers, recent download activity.
|
||||
- Wallet & Billing: prepaid storage is billed from the Ladill wallet (sidebar → Wallet). Top up at account.ladill.com/wallet.
|
||||
- Team: invite teammates to manage transfers together (sidebar → Team).
|
||||
- Settings: notification preferences for transfer activity.
|
||||
|
||||
Pricing:
|
||||
- Storage retention is prepaid at GHS {$pricePerGb} per GB per month (metered on actual storage; no free tier).
|
||||
- Wallet must have funds to keep transfers active through their retention period.
|
||||
|
||||
Rules:
|
||||
- Only answer questions about Ladill QR Plus — code types, styling, downloads, scans, wallet billing, team, and API.
|
||||
- If asked about domains, hosting, email, or payments/commerce QR (shop, events, donations), briefly say those live in other Ladill apps and suggest the app launcher.
|
||||
- Never invent prices, short codes, or wallet balances — use the user context below or tell them where to check.
|
||||
- For print tips: recommend high contrast, adequate quiet zone, test-scan before mass printing.
|
||||
- Only answer questions about Ladill Transfer — uploads, share links, QR codes, passwords, retention/expiry, downloads, storage billing, team, and wallet.
|
||||
- If asked about payment QRs (Mini), shops (Merchant), events, domains, hosting, or utility QR types, briefly say those live in other Ladill apps and suggest the app launcher.
|
||||
- Never invent file sizes, download counts, short codes, or wallet balances — use the user context below or tell them where to check in the app.
|
||||
- Public scan URLs always use ladill.com/q/{code} so printed QRs never need reprinting.
|
||||
|
||||
Current user context:
|
||||
{$ctx}
|
||||
|
||||
Reference in New Issue
Block a user