docs: add sub-project service docs + sync vault 2026-06-08
Add 10 - Services/ docs for all sub-projects: backend, frontend, scanner, deployment (new), update amanat-assist. Update Scanner Architecture, Telegram Mini App flow, and Activity Log. Add payment safety edge cases.
This commit is contained in:
@@ -1,20 +1,22 @@
|
||||
---
|
||||
title: Telegram Mini App Flow
|
||||
tags: [flow, telegram, mini-app, auth, bilingual, RTL, shop, cart]
|
||||
tags: [flow, telegram, mini-app, auth, bilingual, RTL, shop, cart, payment]
|
||||
related_models: ["[[User]]"]
|
||||
related_apis: ["POST /api/auth/telegram", "[[Auth API]]"]
|
||||
task: "5.4"
|
||||
---
|
||||
|
||||
> **Last updated:** 2026-06-03
|
||||
> **Last updated:** 2026-06-08
|
||||
> **Status:** IN PROGRESS — Task 5.4 (dependencies: 5.1 auth infra, 5.2 Telegram sign-in endpoint)
|
||||
> **Frontend branch:** `integrate-main-into-development` · v2.8.94
|
||||
> **Frontend branch:** `integrate-main-into-development` · v2.8.94+
|
||||
> **Entry point:** `src/sections/telegram/` · route `/telegram`
|
||||
|
||||
# Telegram Mini App Flow
|
||||
|
||||
End-to-end specification for the **Amaneh Telegram Mini App** — a fully self-contained marketplace shell surfaced inside Telegram's in-app browser via the WebApp SDK. Buyers and sellers can browse requests, create new escrow requests, shop seller templates, manage a cart, review offer state, follow payments, and message each other without leaving Telegram.
|
||||
|
||||
> **Two separate Mini Apps exist on this platform.** This document covers the **main marketplace Mini App** (`amn.gg/telegram`) built inside the primary Next.js frontend. For the AI-assisted request-creation Mini App, see [[amanat-assist]].
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture Overview
|
||||
@@ -26,10 +28,11 @@ Telegram Client
|
||||
├─ useTelegramLiveContext ← SDK probe + polling
|
||||
├─ useTelegramLanguage ← EN / FA detection
|
||||
├─ useTelegramAutoSignIn ← silent JWT exchange
|
||||
├─ useTelegramMainButton ← native chrome sync
|
||||
├─ useTelegramMainButton ← native chrome sync (disabled)
|
||||
├─ useTelegramBackButton ← native chrome sync
|
||||
├─ useTelegramHaptic ← haptic wrapper
|
||||
├─ useTelegramCart ← shared localStorage cart
|
||||
├─ useTelegramNotifications ← unread badge count
|
||||
│
|
||||
├─ [state: loading] → TelegramLoadingState
|
||||
├─ [state: unsupported] → TelegramUnsupportedState
|
||||
@@ -38,17 +41,28 @@ Telegram Client
|
||||
├─ TelegramHeader
|
||||
├─ TelegramTabBar (Home / Shop / Requests / Chat / Account)
|
||||
│
|
||||
├─ [drilldown] TelegramPaymentView ← highest priority
|
||||
├─ [drilldown] TelegramChatThreadView
|
||||
├─ [drilldown] TelegramRequestDetailView
|
||||
├─ [drilldown] TelegramTemplateDetailView
|
||||
├─ [drilldown] TelegramSellerShopView
|
||||
│
|
||||
├─ [overlay] TelegramPointsView
|
||||
├─ [overlay] TelegramSettingsView
|
||||
├─ [overlay] TelegramAddressesView
|
||||
├─ [overlay] TelegramCartView
|
||||
├─ [overlay] TelegramCheckoutView
|
||||
├─ [overlay] TelegramNotificationsView
|
||||
├─ [overlay] TelegramNewRequestView
|
||||
│
|
||||
├─ TelegramHomeView
|
||||
├─ TelegramShopView → TelegramSellerShopView
|
||||
├─ TelegramRequestsView → TelegramRequestDetailView
|
||||
├─ TelegramChatView → TelegramChatThreadView
|
||||
├─ TelegramAccountView
|
||||
└─ [overlay] TelegramNewRequestView
|
||||
└─ [overlay] TelegramNotificationsView
|
||||
└─ [overlay] TelegramCartView
|
||||
└─ TelegramAccountView
|
||||
```
|
||||
|
||||
The shell is a **single-page, no-router** design: all navigation (tabs, overlays, detail drilldowns) is pure React state in `TelegramMiniAppView`. `window.location.assign` is only used as a final escape hatch to the full web dashboard.
|
||||
The shell is a **single-page, no-router** design: all navigation (tabs, overlays, detail drilldowns) is pure React state in `TelegramMiniAppView`. `window.location.assign` is used only as a final escape hatch to external URLs. `openTelegramExternalLink` is used for deep links into the web dashboard, which opens inside Telegram's WebView or an external browser depending on the Telegram client.
|
||||
|
||||
---
|
||||
|
||||
@@ -66,7 +80,27 @@ The shell is a **single-page, no-router** design: all navigation (tabs, overlays
|
||||
|
||||
---
|
||||
|
||||
## 3. SDK Initialisation & Context Probe
|
||||
## 3. amanat-assist vs Main Mini App
|
||||
|
||||
Two distinct Telegram Mini Apps exist for this platform:
|
||||
|
||||
| Property | Main Mini App (this doc) | amanat-assist |
|
||||
|---|---|---|
|
||||
| URL | `amn.gg/telegram` | `assist.amn.gg` |
|
||||
| Bot | AmanehBot | AmanehBot (same) |
|
||||
| Codebase | `frontend/` (Next.js, `src/sections/telegram/`) | `/amanat-assist` (React + Vite, separate repo) |
|
||||
| Purpose | Full marketplace shell: browse, buy, sell, chat, manage account | Conversational LLM wizard to create one purchase request |
|
||||
| LLM | None | Mistral → DeepSeek fallback (via `amanat-llm-proxy` on port 3001) |
|
||||
| Backend access | Direct calls to `api.amn.gg` | Proxied through `amanat-llm-proxy` which holds the LLM API keys |
|
||||
| Auth | Telegram `initData` → `POST /api/auth/telegram` | Same endpoint; also supports web redirect via `?access_token=` |
|
||||
| Deep links between apps | Main Mini App has "New Request" overlay with an "Open Assist" CTA that navigates `window.location.href` to `assist.amn.gg?access_token=...` | Assist submits the finished request then the user returns to the main app |
|
||||
| Status | In production | Live at `assist.amn.gg` v1.1.0 |
|
||||
|
||||
**Hand-off from main app to assist:** `handleOpenAssist()` in `TelegramMiniAppView` constructs a URL to `https://assist.amn.gg` with `access_token`, `user_json`, `theme`, and `source=miniapp` query params. `window.location.href` is used (not `openLink`) to keep the navigation inside Telegram's WebView rather than opening Safari on iOS.
|
||||
|
||||
---
|
||||
|
||||
## 4. SDK Initialisation & Context Probe
|
||||
|
||||
**File:** `src/utils/telegram-webapp.ts` · `getTelegramContext()`
|
||||
|
||||
@@ -92,7 +126,7 @@ The function assembles a `TelegramContext` object from:
|
||||
|
||||
---
|
||||
|
||||
## 4. Shell State Machine
|
||||
## 5. Shell State Machine
|
||||
|
||||
`getTelegramStatus(context, hasWebAccount)` returns one of three states:
|
||||
|
||||
@@ -114,9 +148,9 @@ State transitions occur on:
|
||||
|
||||
---
|
||||
|
||||
## 5. Authentication Flow
|
||||
## 6. Authentication Flow
|
||||
|
||||
### 5.1 Silent Auto Sign-In
|
||||
### 6.1 Silent Auto Sign-In
|
||||
|
||||
**Hook:** `useTelegramAutoSignIn` · **File:** `hooks/use-telegram-auto-sign-in.ts`
|
||||
|
||||
@@ -127,7 +161,7 @@ On mount, if `context.isMiniApp && context.initData && !user`:
|
||||
3. If the backend returns `isNewUser: true`, show `TelegramOnboardingSheet`.
|
||||
4. A `useRef` deduplication guard (`attemptedInitDataRef`) prevents re-runs under React Strict Mode's double-effect behaviour.
|
||||
|
||||
### 5.2 Manual Sign-In (Unlinked State)
|
||||
### 6.2 Manual Sign-In (Unlinked State)
|
||||
|
||||
When `initData` is present but auto sign-in failed (or hasn't run yet), `TelegramUnlinkedState` renders:
|
||||
- **Continue with Telegram** — calls the same `signIn()` function from `useTelegramAutoSignIn`.
|
||||
@@ -136,47 +170,74 @@ When `initData` is present but auto sign-in failed (or hasn't run yet), `Telegra
|
||||
|
||||
When `initData` is absent (accessed via a path that skips Telegram context), only the email/register buttons appear.
|
||||
|
||||
### 5.3 Backend Endpoint
|
||||
### 6.3 Backend Endpoint
|
||||
|
||||
`POST /api/auth/telegram` — expects `{ initData: string }`. Backend verifies the HMAC using the Telegram bot token, extracts `user` from the payload, upserts a `User` record (`telegramId`, `telegramVerified: true`), and issues a JWT + refresh token. Returns `{ token, refreshToken, isNewUser }`.
|
||||
|
||||
Registered at `authRoutes.ts` line 24: `router.post("/telegram", ctrl.telegramAuth.bind(ctrl))` — public route, no auth middleware.
|
||||
|
||||
### 6.4 Session Linking (Telegram ↔ Amaneh Account)
|
||||
|
||||
The `POST /api/auth/telegram` endpoint both creates and links accounts:
|
||||
|
||||
- **New Telegram user, no existing Amanat account:** a new `User` is created with `telegramId` set; `isNewUser: true` is returned and the onboarding sheet is shown.
|
||||
- **Existing Amanat account with the same `telegramId`:** the existing user is returned; session continues.
|
||||
- **Existing Amanat account that has never used Telegram:** `telegramId` and `telegramVerified: true` are written onto the existing record (matched by Telegram user id).
|
||||
|
||||
After the JWT is issued the standard `checkUserSession()` re-hydrates the React auth context. The Mini App shell reads `user.telegramVerified` and `user.isEmailVerified` from this context to render verification chips in the Account tab.
|
||||
|
||||
---
|
||||
|
||||
## 6. Navigation Model
|
||||
## 7. Navigation Model
|
||||
|
||||
All navigation is in-shell React state — no Next.js router is involved.
|
||||
|
||||
```
|
||||
activeTab : 'home' | 'shop' | 'requests' | 'chat' | 'account'
|
||||
overlayScreen : 'new-request' | 'notifications' | 'cart' | null
|
||||
openConversationId : string | null
|
||||
openRequestId : string | null
|
||||
openSellerId : string | null
|
||||
activeTab : 'home' | 'shop' | 'requests' | 'chat' | 'account'
|
||||
overlayScreen : 'new-request' | 'notifications' | 'cart' | 'checkout'
|
||||
| 'points' | 'settings' | 'addresses' | null
|
||||
openConversationId : string | null
|
||||
openRequestId : string | null
|
||||
openPaymentRequestId : string | null ← payment drilldown (highest priority)
|
||||
paymentCheckoutFlow : boolean ← true when reached from shop checkout
|
||||
openSellerId : string | null
|
||||
openTemplate : { template, seller } | null
|
||||
```
|
||||
|
||||
**Priority rendering** (first match wins):
|
||||
|
||||
1. `openConversationId` → `TelegramChatThreadView`
|
||||
2. `openRequestId` → `TelegramRequestDetailView`
|
||||
3. `openSellerId` → `TelegramSellerShopView`
|
||||
4. `overlayScreen === 'cart'` → `TelegramCartView`
|
||||
5. `overlayScreen === 'notifications'` → `TelegramNotificationsView`
|
||||
6. `overlayScreen === 'new-request'` → `TelegramNewRequestView`
|
||||
7. `activeTab` → appropriate tab view
|
||||
1. `openPaymentRequestId` → `TelegramPaymentView` ← new, highest priority
|
||||
2. `openConversationId` → `TelegramChatThreadView`
|
||||
3. `openRequestId` → `TelegramRequestDetailView`
|
||||
4. `openTemplate` → `TelegramTemplateDetailView` ← new
|
||||
5. `openSellerId` → `TelegramSellerShopView`
|
||||
6. `overlayScreen === 'points'` → `TelegramPointsView` ← new
|
||||
7. `overlayScreen === 'settings'` → `TelegramSettingsView` ← new
|
||||
8. `overlayScreen === 'addresses'` → `TelegramAddressesView` ← new
|
||||
9. `overlayScreen === 'cart'` → `TelegramCartView`
|
||||
10. `overlayScreen === 'checkout'` → `TelegramCheckoutView` ← new (replaces web handoff)
|
||||
11. `overlayScreen === 'notifications'` → `TelegramNotificationsView`
|
||||
12. `overlayScreen === 'new-request'` → `TelegramNewRequestView`
|
||||
13. `activeTab` → appropriate tab view
|
||||
|
||||
**Back button** (Telegram native `BackButton`) dismisses in reverse priority order: chat thread → request detail → seller shop → overlay → returns to `home` tab.
|
||||
**Back button** (Telegram native `BackButton`) dismisses in reverse priority order:
|
||||
- Payment drilldown → if `paymentCheckoutFlow`, steps back to cart; otherwise clears payment state.
|
||||
- Chat thread → clears `openConversationId`.
|
||||
- Request detail → clears `openRequestId`.
|
||||
- Template detail → clears `openTemplate`.
|
||||
- Seller shop → clears `openSellerId`.
|
||||
- Overlay (`checkout` steps back to `cart`) → clears `overlayScreen`.
|
||||
- Non-home tab → returns to `home`.
|
||||
|
||||
`BackButton` visibility: shown whenever `state === 'linked'` and either an overlay/drilldown is active, or `activeTab !== 'home'`.
|
||||
|
||||
`MainButton` visibility: hidden while any overlay is open. When visible:
|
||||
- **Linked** → "New Request" (opens `overlayScreen = 'new-request'`)
|
||||
- **Unlinked** → "Sign In" (navigates to the JWT sign-in page)
|
||||
`MainButton` visibility: **intentionally disabled** (`isReady: false`) — the native Telegram MainButton cannot use the project font and duplicates in-shell CTAs, so it is kept hidden. All primary actions live inside the shell UI itself.
|
||||
|
||||
Both chrome buttons are styled with the amaneh saffron palette (`color: #C2410C`, `text_color: #FFFFFF`) via `setParams` (WebApp SDK >= 6.1).
|
||||
Both chrome buttons retain the amaneh saffron palette (`color: #C2410C`, `text_color: #FFFFFF`) via `setParams` (WebApp SDK >= 6.1) as a fallback should the MainButton ever be re-enabled.
|
||||
|
||||
---
|
||||
|
||||
## 7. Tab Structure
|
||||
## 8. Tab Structure
|
||||
|
||||
The shell has **five bottom tabs** rendered by `TelegramTabBar`:
|
||||
|
||||
@@ -192,89 +253,115 @@ The shell has **five bottom tabs** rendered by `TelegramTabBar`:
|
||||
|
||||
---
|
||||
|
||||
## 8. Supported Flows
|
||||
## 9. Supported Flows
|
||||
|
||||
### 8.1 Home Tab
|
||||
### 9.1 Home Tab
|
||||
|
||||
`TelegramHomeView` is the landing screen shown on first open. It contains:
|
||||
- **Welcome banner** (`TelegramWelcomeBanner`): escrow account summary, primary CTA.
|
||||
- **Quick-action cards** (`TelegramQuickActions`): shortcuts to Requests, Payments, Chat.
|
||||
- **Escrow state chips** (`TelegramEscrowStateChips`): legend of status values visible in the platform.
|
||||
- **"New Request" CTA** → opens `overlayScreen = 'new-request'`.
|
||||
- **"Open Assist" CTA** → calls `handleOpenAssist()` to navigate to `assist.amn.gg` in the same WebView (see section 3).
|
||||
|
||||
### 8.2 Shop Tab — Sellers List
|
||||
### 9.2 Shop Tab — Sellers List
|
||||
|
||||
**`TelegramShopView`** (`telegram-shop-view.tsx`):
|
||||
- Fetches all sellers via `useTelegramShops()` → SWR wrapping `getTemplateSellers()` → `GET /api/request-templates/sellers`.
|
||||
- Renders `TelegramShopRow` per seller: avatar, name, rating, template count, sales count.
|
||||
- Shows a floating cart badge button in the header when `totalItems > 0`; tap opens `overlayScreen = 'cart'`.
|
||||
- Shows a floating cart badge button (`TelegramCartFab`) in the header when `totalItems > 0`; tap opens `overlayScreen = 'cart'`.
|
||||
- Tap a seller row → sets `openSellerId` → navigates to `TelegramSellerShopView`.
|
||||
|
||||
### 8.3 Shop Tab — Seller Store
|
||||
### 9.3 Shop Tab — Seller Store
|
||||
|
||||
**`TelegramSellerShopView`** (`telegram-seller-shop-view.tsx`):
|
||||
- Fetches seller + active templates via `useTelegramSellerShop(sellerId)` → `GET /api/request-templates/sellers/:id`.
|
||||
- Dark header: seller avatar, name, rating, template count, description.
|
||||
- Each template card shows: image, title, 2-line description, budget range, usage count.
|
||||
- **Two actions per template:**
|
||||
- **Add to cart / Remove from cart** — toggles item in `useTelegramCart` (localStorage, no API). Button is filled blue when not in cart, outline when added.
|
||||
- **Order this template** — `<a href>` to `/dashboard/request/from-template?shareableLink=...`. Exits the Mini App to the web dashboard (single-template direct order, bypasses cart).
|
||||
- **Add to cart / Remove from cart** — toggles item in `useTelegramCart` (localStorage, no API).
|
||||
- **View template details** — sets `openTemplate` → navigates to `TelegramTemplateDetailView`.
|
||||
- Floating "Cart · N templates" sticky button at bottom when `totalItems > 0`; tap calls `onOpenCart()`.
|
||||
|
||||
### 8.4 Shopping Cart Overlay
|
||||
### 9.4 Shop Tab — Template Detail
|
||||
|
||||
**`TelegramTemplateDetailView`** (`telegram-template-detail-view.tsx`):
|
||||
- Full-screen view of a single template.
|
||||
- Shows full description, seller info, price, delivery info, usage/capacity counters.
|
||||
- Add/remove cart action; direct "Order this template" link to `/dashboard/request/from-template?shareableLink=...` (exits to web dashboard).
|
||||
- Back button returns to the seller store (`openTemplate` cleared, `openSellerId` retained).
|
||||
|
||||
### 9.5 Shopping Cart Overlay
|
||||
|
||||
**`TelegramCartView`** (`telegram-cart-view.tsx`):
|
||||
- Rendered as `overlayScreen = 'cart'`; dismissed by Telegram BackButton.
|
||||
- Lists each cart item: image, name, seller name, USDT price × quantity, +/− quantity controls, remove button.
|
||||
- Subtotal/total in USDT, locale-formatted (`fa-IR` for Persian, `en-US` for English); amounts always `dir="ltr"`.
|
||||
- **"Continue to payment"** — plain `<a href={paths.shops.checkout}>` link; exits Mini App to web checkout.
|
||||
- **"Continue to payment"** → calls `onCheckout()` which sets `overlayScreen = 'checkout'` (in-shell checkout, replacing the previous web handoff).
|
||||
|
||||
**Cart storage (`useTelegramCart`):**
|
||||
|
||||
- Reads/writes `localStorage` key **`app-request-template-checkout`** — the same key the web `RequestTemplateCheckoutProvider` reads. This is the cart handoff mechanism: the cart built in Telegram IS the cart the web checkout page hydrates.
|
||||
- Reads/writes `localStorage` key **`app-request-template-checkout`** — the same key the web `RequestTemplateCheckoutProvider` reads. This enables the web dashboard checkout to hydrate the same cart.
|
||||
- Dispatches a custom `tg-cart-changed` DOM event on every write; listens on both that event and the native `storage` event so all open tabs stay in sync.
|
||||
- Operations: `addTemplate(template, seller)`, `removeItem(itemId)`, `changeQuantity(itemId, qty)`, `isInCart(templateId)`.
|
||||
- No API calls — cart is purely client-side until checkout.
|
||||
- Cart item model: `id`, `templateId`, `name`, `description`, `price` (from `template.budget.min`), `quantity`, `image`, `sellerId`, `sellerName`, `category`, `shareableLink`, `deliveryInfo`, `maxUsage`, `usageCount`, `remainingCapacity`.
|
||||
|
||||
### 8.5 Web Checkout Handoff
|
||||
### 9.6 In-Shell Checkout Overlay
|
||||
|
||||
Destination: `/dashboard/shops/checkout` — `RequestTemplateCheckoutView` wrapped by `RequestTemplateCheckoutProvider`.
|
||||
**`TelegramCheckoutView`** (`telegram-checkout-view.tsx`):
|
||||
- Rendered as `overlayScreen = 'checkout'`; BackButton steps back to `overlayScreen = 'cart'`.
|
||||
- A 3-step stepper running entirely inside the Mini App shell:
|
||||
- **Step 0 (Cart review):** item list, quantities, totals, discount.
|
||||
- **Step 1 (Address):** physical address or online delivery email.
|
||||
- **Step 2 (Payment):** wallet-based payment execution.
|
||||
- On successful order (`onPlaced(reqId)` callback):
|
||||
- If a `reqId` is returned, sets `paymentCheckoutFlow = true` and `openPaymentRequestId = reqId` → immediately opens the payment view.
|
||||
- If no `reqId`, switches `activeTab` to `'requests'`.
|
||||
- Stock validation clamps or removes items exceeding `remainingCapacity` before payment.
|
||||
- Integrates with `onManageAddresses()` to open the `addresses` overlay mid-flow.
|
||||
|
||||
The provider reads the shared `localStorage` key and hydrates the TMA cart. The checkout is a 3-step stepper:
|
||||
### 9.7 Payment View (In-Shell)
|
||||
|
||||
| Step | Component | Description |
|
||||
|---|---|---|
|
||||
| 0 (Cart review) | `RequestTemplateCheckoutCart` | Item list, quantities, remove, totals, discount/shipping |
|
||||
| 1 (Address) | `RequestTemplateCheckoutBillingAddress` | Physical address or online delivery email |
|
||||
| 2 (Payment) | `RequestTemplateCheckoutPayment` | Wallet payment + socket confirmation |
|
||||
| Complete | `RequestTemplateCheckoutOrderComplete` | Confirmation dialog, cart reset |
|
||||
**`TelegramPaymentView`** (`telegram-payment-view.tsx`):
|
||||
- Highest-priority drilldown (rendered before all other overlays).
|
||||
- Loaded for a specific `requestId`. Used from two entry points:
|
||||
- **Shop checkout flow** (`paymentCheckoutFlow = true`): after `TelegramCheckoutView` creates the requests. Shows a 3-step progress header (cart → address → payment).
|
||||
- **Requests tab** (`paymentCheckoutFlow = false`): buyer taps "Pay" on an existing request. No progress header.
|
||||
- Fetches request details via `useTelegramRequest`.
|
||||
- Fetches offers via `useTelegramOffers`.
|
||||
- Calls `getPaymentOptions()` → `GET /api/payment/options` and `createDirectBalanceIntent()` → `POST /api/payment/direct-balance`.
|
||||
- Polls `checkDirectBalancePayment()` for confirmation.
|
||||
- On successful payment: calls `onPaid()` → clears `openPaymentRequestId`, switches to `activeTab = 'requests'`.
|
||||
- Back button: if `paymentCheckoutFlow`, steps back to `overlayScreen = 'cart'`; otherwise clears the payment state.
|
||||
|
||||
Payment execution calls `convertTemplatesToRequests()` to create escrow records, then awaits a `template-checkout-payment-confirmed` socket event. A guard checks `createdRequestIds` is non-empty before advancing (prevents stray global socket events from triggering premature completion). Stock validation clamps or removes items exceeding `remainingCapacity` before payment.
|
||||
|
||||
### 8.6 Browse Requests (Requests Tab)
|
||||
### 9.8 Browse Requests (Requests Tab)
|
||||
|
||||
- `TelegramRequestsView` fetches the user's purchase requests via `useTelegramMyRequests` (GET `/api/requests`).
|
||||
- Displays a skeleton loader, then a scrollable list of `TelegramRequestRow` items.
|
||||
- Each row shows: title, status chip, budget, creation date.
|
||||
- Tap → sets `openRequestId` → renders `TelegramRequestDetailView`.
|
||||
|
||||
### 8.7 Request Detail with Stepper
|
||||
### 9.9 Request Detail with Stepper and Offers
|
||||
|
||||
- `TelegramRequestDetailView` fetches a single request via `useTelegramRequest`.
|
||||
- Renders `TelegramRequestStepper` — a visual timeline of the escrow status flow from `pending_payment` → `completed`.
|
||||
- `determineCurrentStepFromStatus` maps the current `status` to a step index.
|
||||
- Also renders: budget, description, creation date, category, urgency.
|
||||
- **Offer review:** fetches offers via `useTelegramOffers`; renders offer cards with seller info, price, and accept/reject actions.
|
||||
- **Pay action:** renders a "Pay" button when request is in a payable state → calls `onPay(id)` → sets `openPaymentRequestId`.
|
||||
- **Web fallback:** "View full details" → `openTelegramExternalLink(context.webApp, path)`.
|
||||
- **Chat seller:** taps the seller chat icon → calls `onChatSeller(sellerId)` → `createConversation` + sets `openConversationId`.
|
||||
- Role-aware: `role` prop is `'seller'` or `'buyer'` based on `user.role`.
|
||||
- Dates formatted via `toLocaleDateString` with `fa-IR` locale for Persian.
|
||||
|
||||
### 8.8 Create New Request
|
||||
### 9.10 Create New Request
|
||||
|
||||
- `TelegramNewRequestView` is a full-screen overlay (not a routed page).
|
||||
- Form fields: title, description, category (fetched from `/api/categories`), budget min/max, urgency.
|
||||
- Includes an **"Open Assist"** button that delegates to `handleOpenAssist()` for users who prefer the conversational LLM flow.
|
||||
- On submit: calls `createPurchaseRequest()` → POST `/api/purchase-requests`.
|
||||
- On success: closes overlay, switches `activeTab` to `'requests'`.
|
||||
- `MainButton` is hidden while the overlay is open (submit lives in the form itself).
|
||||
|
||||
### 8.9 Chat Tab
|
||||
### 9.11 Chat Tab
|
||||
|
||||
- `TelegramChatView` shows the user's active conversations via `useTelegramConversations`.
|
||||
- Includes a Support row that calls `createSupportChat()` → `POST /api/chat/support`, then opens `TelegramChatThreadView` with the returned conversation ID.
|
||||
@@ -283,22 +370,21 @@ Payment execution calls `convertTemplatesToRequests()` to create escrow records,
|
||||
- Optimistic send: message appears immediately, confirmed/rolled back on API response.
|
||||
- Real-time updates via Socket.IO events; SWR is mutated on `new-notification` and `unread-count-update` events.
|
||||
|
||||
### 8.10 Account Tab
|
||||
### 9.12 Account Tab
|
||||
|
||||
**`TelegramAccountView`** (`telegram-account-view.tsx`):
|
||||
|
||||
The account tab has four sections. All user data is passed as props from the shell (loaded via `useAuthContext()` — no fetch on mount).
|
||||
|
||||
**Profile header:**
|
||||
- Avatar (from `user.profile.avatar`, falls back to initials), full name, Telegram `@username`, role chip (buyer / seller / admin / resolver / guard).
|
||||
- Verification chips: "Telegram Verified" (if `user.telegramVerified`) and "Email Verified" (if `user.isEmailVerified`).
|
||||
|
||||
**Preferences section:**
|
||||
- Language toggle (FA / EN, in-shell via `TelegramLanguageToggle`).
|
||||
- General Settings → `/dashboard/account` (web, labeled "Opens in the web dashboard").
|
||||
- Wallet → truncated address (`0x1234…abcd`) or "not connected" → `/dashboard/account/wallet` (web).
|
||||
- **Settings** → opens `overlayScreen = 'settings'` (in-shell `TelegramSettingsView`).
|
||||
- **Points** → opens `overlayScreen = 'points'` (in-shell `TelegramPointsView`).
|
||||
- Wallet → truncated address (`0x1234…abcd`) or "not connected" → `/dashboard/account/wallet` (web via `openTelegramExternalLink`).
|
||||
- Notifications → opens `TelegramNotificationsView` overlay in-shell.
|
||||
- Addresses → `/dashboard/account/address` (web).
|
||||
- **Addresses** → opens `overlayScreen = 'addresses'` (in-shell `TelegramAddressesView`).
|
||||
- Passkey → `/dashboard/account/passkey` (web).
|
||||
|
||||
**Help section:**
|
||||
@@ -308,16 +394,38 @@ The account tab has four sections. All user data is passed as props from the she
|
||||
**Session section:**
|
||||
- Sign Out → `TelegramBottomSheet` confirmation dialog → `authSignOut()` + `window.location.assign(paths.auth.jwt.signIn)`.
|
||||
|
||||
### 8.11 Notifications Overlay
|
||||
### 9.13 Settings Overlay
|
||||
|
||||
**`TelegramSettingsView`** (`telegram-settings-view.tsx`):
|
||||
- Rendered as `overlayScreen = 'settings'`.
|
||||
- Allows editing profile fields (name, bio) in-shell.
|
||||
- On save: calls `onSaved()` which triggers `checkUserSession()` to refresh the auth context.
|
||||
|
||||
### 9.14 Addresses Overlay
|
||||
|
||||
**`TelegramAddressesView`** (`telegram-addresses-view.tsx`):
|
||||
- Rendered as `overlayScreen = 'addresses'`.
|
||||
- Fetches addresses via `use-telegram-addresses.ts`.
|
||||
- Used both from the Account tab and as a mid-flow step from `TelegramCheckoutView`.
|
||||
|
||||
### 9.15 Points Overlay
|
||||
|
||||
**`TelegramPointsView`** (`telegram-points-view.tsx`):
|
||||
- Rendered as `overlayScreen = 'points'`.
|
||||
- Fetches user points via `use-telegram-points.ts`.
|
||||
- Shows points balance and transaction history.
|
||||
|
||||
### 9.16 Notifications Overlay
|
||||
|
||||
- `TelegramNotificationsView` is rendered as `overlayScreen = 'notifications'`.
|
||||
- Fetches via `useTelegramNotifications` → `getNotifications(userId, 1, 50)` → `GET /api/notifications?userId=...&page=1&limit=50`.
|
||||
- Real-time updates: Socket.IO events `new-notification`, `unread-count-update` trigger SWR mutate.
|
||||
- "Mark all read" calls `markAllNotificationsAsRead(userId)` → `PATCH /api/notifications/mark-all-read`.
|
||||
- Unread count is also surfaced in the `TelegramHeader` bell icon badge.
|
||||
|
||||
---
|
||||
|
||||
## 9. API Calls
|
||||
## 10. API Calls
|
||||
|
||||
| Action | Hook / call | Backend endpoint |
|
||||
|---|---|---|
|
||||
@@ -328,18 +436,26 @@ The account tab has four sections. All user data is passed as props from the she
|
||||
| My requests | `useTelegramMyRequests` | `GET /api/requests` |
|
||||
| Single request | `useTelegramRequest` | `GET /api/purchase-requests/:id` |
|
||||
| Create request | shell → `createPurchaseRequest()` | `POST /api/purchase-requests` |
|
||||
| Offers for request | `useTelegramOffers` → `getOffers(requestId)` | `GET /api/marketplace/offers?requestId=...` |
|
||||
| Payment options | `getPaymentOptions()` | `GET /api/payment/options` |
|
||||
| Create payment intent | `createDirectBalanceIntent()` | `POST /api/payment/direct-balance` |
|
||||
| Poll payment status | `checkDirectBalancePayment()` | `GET /api/payment/:id` |
|
||||
| Update request status | `updateRequestStatus()` | `PATCH /api/marketplace/requests/:id/status` |
|
||||
| Conversations | `useTelegramConversations` | `GET /api/chat/conversations` |
|
||||
| Chat thread | `useTelegramChatThread` | `GET /api/chat/:id` + Socket.IO real-time |
|
||||
| Support chat | `createSupportChat()` | `POST /api/chat/support` |
|
||||
| Direct conversation | `createConversation({ type: 'direct', participantIds })` | `POST /api/chat/conversations` |
|
||||
| Notifications | `useTelegramNotifications` | `GET /api/notifications?userId=...&page=1&limit=50` |
|
||||
| Mark all read | `markAllNotificationsAsRead(userId)` | `PATCH /api/notifications/mark-all-read` |
|
||||
| Auth sign-out | `authSignOut()` | JWT sign-out endpoint |
|
||||
| Addresses | `use-telegram-addresses.ts` | `GET /api/user/addresses` |
|
||||
| Points | `use-telegram-points.ts` | `GET /api/user/points` |
|
||||
|
||||
Cart operations (add/remove/quantity) are **pure localStorage** — no API calls until web checkout.
|
||||
Cart operations (add/remove/quantity) are **pure localStorage** — no API calls until checkout.
|
||||
|
||||
---
|
||||
|
||||
## 10. Bilingual Support (EN / FA)
|
||||
## 11. Bilingual Support (EN / FA)
|
||||
|
||||
**Language detection priority** (`useTelegramLanguage`):
|
||||
|
||||
@@ -378,7 +494,7 @@ All JSX uses `t.<section>.<key>` — no inline strings in components.
|
||||
|
||||
---
|
||||
|
||||
## 11. Design System
|
||||
## 12. Design System
|
||||
|
||||
**File:** `src/sections/telegram/constants.ts` · `src/sections/telegram/telegram-shell-css.ts`
|
||||
|
||||
@@ -391,7 +507,7 @@ The Mini App has a distinct visual identity (cream/saffron Persian palette) that
|
||||
| `cream50` | `#FBF6EB` | Page background |
|
||||
| `ink900` | `#1C1410` | Primary text |
|
||||
| `ink600` | `#6B5D4E` | Secondary text / labels |
|
||||
| `saffron600` | `#C2410C` | Primary action, MainButton |
|
||||
| `saffron600` | `#C2410C` | Primary action |
|
||||
| `saffron500` | `#D97757` | Hover states |
|
||||
| `pistachio700` | `#3D6B4F` | Success / released states |
|
||||
| `pomegranate700` | `#8E2424` | Error / disputed states |
|
||||
@@ -399,15 +515,15 @@ The Mini App has a distinct visual identity (cream/saffron Persian palette) that
|
||||
|
||||
**Fonts:** `TG_FONTS` — Source Serif 4 (headings), IBM Plex Sans (body LTR), Vazirmatn (body RTL), IBM Plex Mono (amounts/addresses).
|
||||
|
||||
**CSS:** `buildTelegramShellCss()` injects a `<style>` tag at shell root with all class utilities (`.tg-chip`, `.tg-shell`, `.tg-tab-bar`, `.tg-header`, etc.). Theme CSS variables (`--cream-50`, `--ink-900`, etc.) are set on `.tg-shell` root.
|
||||
**CSS:** `buildTelegramShellCss()` injects a `<style>` tag at shell root with all class utilities (`.tg-chip`, `.tg-shell`, `.tg-tab-bar`, `.tg-header`, etc.). Theme CSS variables (`--cream-50`, `--ink-900`, etc.) are set on `.tg-shell` root. Dark mode: `.tg-shell--dark` class toggled from `themeScheme`.
|
||||
|
||||
**Safe area:** `getTelegramSafeAreaStyle(safeArea)` maps the Telegram-reported safe area insets to CSS padding using `max(${px}px, env(safe-area-inset-*))` to handle both Telegram-native and iOS/Android safe areas.
|
||||
|
||||
---
|
||||
|
||||
## 12. Telegram SDK Usage Patterns
|
||||
## 13. Telegram SDK Usage Patterns
|
||||
|
||||
### 12.1 Safe-Area Inset
|
||||
### 13.1 Safe-Area Inset
|
||||
|
||||
```ts
|
||||
// TelegramContext.safeArea = { top, right, bottom, left } (px)
|
||||
@@ -418,16 +534,16 @@ const topInset = (context.safeArea?.top ?? 0) as number;
|
||||
|
||||
All views receive `topInset` / `bottomInset` props and add them as explicit `paddingTop` / `paddingBottom` to avoid content being obscured by the Telegram chrome.
|
||||
|
||||
### 12.2 Haptic Feedback
|
||||
### 13.2 Haptic Feedback
|
||||
|
||||
```ts
|
||||
// useTelegramHaptic(webApp) → haptic('light' | 'medium')
|
||||
webApp?.HapticFeedback?.impactOccurred?.(type)
|
||||
```
|
||||
|
||||
Used on: tab switches (light), new-request CTA (medium), language toggle (light), back button (light). All calls are wrapped in try/catch — the API may be absent on older clients.
|
||||
Used on: tab switches (light), new-request CTA (medium), language toggle (light), back button (light), payment actions (medium). All calls are wrapped in try/catch — the API may be absent on older clients.
|
||||
|
||||
### 12.3 Back Button
|
||||
### 13.3 Back Button
|
||||
|
||||
```ts
|
||||
useTelegramBackButton({ webApp, isVisible, onClick })
|
||||
@@ -435,22 +551,29 @@ useTelegramBackButton({ webApp, isVisible, onClick })
|
||||
// Cleanup: offClick() on unmount / visibility change
|
||||
```
|
||||
|
||||
### 12.4 Main Button
|
||||
### 13.4 Main Button
|
||||
|
||||
```ts
|
||||
useTelegramMainButton({ webApp, isReady, text, onClick })
|
||||
// Calls webApp.MainButton.show() / hide(), setText(), setParams()
|
||||
// Saffron palette: color: '#C2410C', text_color: '#FFFFFF'
|
||||
// setParams requires WebApp >= 6.1; silent fallback for older clients
|
||||
useTelegramMainButton({ webApp, isReady: false, text: '', onClick: mainButtonAction })
|
||||
// isReady is always false — MainButton is intentionally kept hidden.
|
||||
// The hook is retained so it can be re-enabled without structural changes.
|
||||
```
|
||||
|
||||
### 12.5 Theme Integration
|
||||
### 13.5 External Links
|
||||
|
||||
Telegram's `themeParams` is normalised (both camelCase and snake_case accepted) and injected as CSS custom properties on the shell root (`--telegram-shell-bg`, `--telegram-shell-text`, etc.). The amaneh palette overrides these for the Mini App's own UI, but components can reference them for adaptive behaviours.
|
||||
```ts
|
||||
openTelegramExternalLink(context.webApp, path)
|
||||
// Uses webApp.openLink() for fully external URLs (opens browser).
|
||||
// Uses window.location.href for same-origin navigation that must stay in WebView.
|
||||
```
|
||||
|
||||
### 13.6 Theme Integration
|
||||
|
||||
Telegram's `themeParams` is normalised (both camelCase and snake_case accepted) and injected as CSS custom properties on the shell root. The amaneh palette overrides these for the Mini App's own UI.
|
||||
|
||||
---
|
||||
|
||||
## 13. Edge Cases
|
||||
## 14. Edge Cases
|
||||
|
||||
| Scenario | Detection | Handling |
|
||||
|---|---|---|
|
||||
@@ -467,11 +590,14 @@ Telegram's `themeParams` is normalised (both camelCase and snake_case accepted)
|
||||
| Persian locale date formatting | `lang === 'fa'` | `toLocaleDateString('fa-IR', ...)` in `formatDate` helper |
|
||||
| Cart cross-tab sync | Multiple tabs / Mini App + web | `tg-cart-changed` DOM event + `storage` event both trigger re-render |
|
||||
| Template at capacity | `remainingCapacity === 0` at checkout | Stock validation clamps/removes over-capacity items before payment |
|
||||
| Stray global socket on checkout | `template-checkout-payment-confirmed` fires unexpectedly | Guard checks `createdRequestIds.length > 0` before advancing to completion step |
|
||||
| Payment from shop checkout | `paymentCheckoutFlow === true` | BackButton steps back to cart; progress header shows 3-step flow |
|
||||
| Display name resolution | User may have no name set in DB | Falls back to Telegram profile name (`first_name` / `last_name`), then generic label |
|
||||
| Seller chat from request detail | `onChatSeller(sellerId)` | `createConversation({ type: 'direct', participantIds: [sellerId] })` → opens chat thread in-shell |
|
||||
| Assist hand-off on iOS | `webApp.openLink()` opens Safari | `window.location.href` used instead to keep navigation in the Telegram WebView |
|
||||
|
||||
---
|
||||
|
||||
## 14. File Map
|
||||
## 15. File Map
|
||||
|
||||
```
|
||||
src/
|
||||
@@ -480,6 +606,7 @@ src/
|
||||
sections/telegram/
|
||||
constants.ts # TG_PALETTE, TG_FONTS, TG_EASE, status maps
|
||||
telegram-shell-css.ts # buildTelegramShellCss() — inlined CSS blob
|
||||
avatar-url.ts # avatar URL helper
|
||||
index.ts # barrel
|
||||
locales/
|
||||
types.ts # TelegramDict, TelegramLang, TelegramTabId
|
||||
@@ -490,35 +617,47 @@ src/
|
||||
use-telegram-live-context.ts # SDK polling
|
||||
use-telegram-language.ts # EN/FA detection + ?lang= + localStorage persist
|
||||
use-telegram-auto-sign-in.ts # initData → JWT exchange
|
||||
use-telegram-main-button.ts # MainButton lifecycle
|
||||
use-telegram-main-button.ts # MainButton lifecycle (kept, isReady=false)
|
||||
use-telegram-back-button.ts # BackButton lifecycle
|
||||
use-telegram-haptic.ts # HapticFeedback wrapper
|
||||
use-telegram-cart.ts # localStorage cart (shared with web checkout)
|
||||
use-telegram-theme.ts # dark/light theme detection
|
||||
use-telegram-realtime.ts # shared Socket.IO real-time helper
|
||||
use-telegram-shops.ts # GET /api/request-templates/sellers
|
||||
use-telegram-seller-shop.ts # GET /api/request-templates/sellers/:id
|
||||
use-telegram-sellers.ts # GET /api/marketplace/sellers
|
||||
use-telegram-my-requests.ts # GET /api/requests
|
||||
use-telegram-request.ts # GET /api/purchase-requests/:id
|
||||
use-telegram-offers.ts # GET /api/marketplace/offers?requestId=...
|
||||
use-telegram-conversations.ts # Chat conversation list
|
||||
use-telegram-chat-thread.ts # Chat thread + optimistic send
|
||||
use-telegram-notifications.ts # GET /api/notifications
|
||||
use-telegram-addresses.ts # GET /api/user/addresses
|
||||
use-telegram-points.ts # GET /api/user/points
|
||||
index.ts
|
||||
view/
|
||||
telegram-mini-app-view.tsx # Shell orchestrator (all state lives here)
|
||||
telegram-home-view.tsx # Home tab
|
||||
telegram-shop-view.tsx # Shop tab — sellers list
|
||||
telegram-seller-shop-view.tsx # Seller store drill-down + cart actions
|
||||
telegram-template-detail-view.tsx # Template full detail + cart/order actions
|
||||
telegram-cart-view.tsx # Cart overlay
|
||||
telegram-checkout-view.tsx # In-shell 3-step checkout overlay
|
||||
telegram-payment-view.tsx # In-shell payment drilldown
|
||||
telegram-requests-view.tsx # Requests list tab
|
||||
telegram-request-detail-view.tsx # Request drilldown + stepper
|
||||
telegram-new-request-view.tsx # New request overlay form
|
||||
telegram-request-detail-view.tsx # Request drilldown + stepper + offers
|
||||
telegram-new-request-view.tsx # New request overlay form + Assist CTA
|
||||
telegram-chat-view.tsx # Chat conversation list tab
|
||||
telegram-chat-thread-view.tsx # Chat thread drilldown
|
||||
telegram-archived-chats-view.tsx # Archived conversations
|
||||
telegram-account-view.tsx # Account + preferences + sign-out tab
|
||||
telegram-notifications-view.tsx # Notifications overlay
|
||||
telegram-settings-view.tsx # In-shell profile/settings overlay
|
||||
telegram-addresses-view.tsx # In-shell address management overlay
|
||||
telegram-points-view.tsx # In-shell points/loyalty overlay
|
||||
index.ts
|
||||
components/
|
||||
telegram-header.tsx # AMN logo + subtitle + language toggle
|
||||
telegram-header.tsx # AMN logo + subtitle + language toggle + bell
|
||||
telegram-tab-bar.tsx # Bottom tab bar (5 tabs)
|
||||
telegram-welcome-banner.tsx # Home: escrow account banner + CTA
|
||||
telegram-quick-actions.tsx # Home: action cards (Requests / Payments / Chat)
|
||||
@@ -528,17 +667,22 @@ src/
|
||||
telegram-request-stepper.tsx # Detail: visual escrow timeline
|
||||
telegram-list-row.tsx # Generic list row primitive
|
||||
telegram-list-skeleton.tsx # Skeleton loader for lists
|
||||
telegram-list-controls.tsx # List sort/filter controls
|
||||
telegram-chat-row.tsx # Chat: conversation list row
|
||||
telegram-chat-bubble.tsx # Chat: message bubble
|
||||
telegram-chat-composer.tsx # Chat: message input
|
||||
telegram-review-prompt.tsx # Post-transaction review prompt
|
||||
telegram-loading-state.tsx # Loading spinner state
|
||||
telegram-unlinked-state.tsx # Unlinked / sign-in prompt state
|
||||
telegram-unsupported-state.tsx # Not-in-Telegram fallback state
|
||||
telegram-onboarding-sheet.tsx # New-user onboarding bottom sheet
|
||||
telegram-empty-state.tsx # Generic empty list state
|
||||
telegram-language-toggle.tsx # EN | FA header toggle
|
||||
telegram-theme-toggle.tsx # Dark / light theme toggle
|
||||
telegram-bottom-sheet.tsx # Generic bottom sheet primitive
|
||||
telegram-form-field.tsx # Form field + input style helper
|
||||
telegram-cart-fab.tsx # Floating cart badge button
|
||||
telegram-support-fab.tsx # Floating support chat button
|
||||
telegram-seal-mark.tsx # SealMark logo component
|
||||
telegram-icons.tsx # Telegram-scoped icon set
|
||||
index.ts
|
||||
@@ -546,7 +690,7 @@ src/
|
||||
|
||||
---
|
||||
|
||||
## 15. Current Implementation Status (v2.8.94)
|
||||
## 16. Current Implementation Status
|
||||
|
||||
| Area | Status | Notes |
|
||||
|---|---|---|
|
||||
@@ -556,39 +700,54 @@ src/
|
||||
| Manual sign-in (unlinked) | Done | Email + create account fallbacks |
|
||||
| Bilingual EN/FA | Done | Full string inventory, RTL layout, Vazirmatn font |
|
||||
| Language toggle | Done | Header toggle + localStorage persist |
|
||||
| `?lang=` dev preview param | Done | URL param override added to `useTelegramLanguage` |
|
||||
| Home tab | Done | Banner + quick actions + state chips |
|
||||
| Shop tab — sellers list | Done | API-backed with skeleton + empty states, cart badge |
|
||||
| Shop tab — seller store | Done | Templates list, add/remove cart, direct order link |
|
||||
| `?lang=` dev preview param | Done | URL param override |
|
||||
| Dark mode | Done | `.tg-shell--dark` class, `use-telegram-theme` |
|
||||
| Home tab | Done | Banner + quick actions + state chips + Assist CTA |
|
||||
| Shop tab — sellers list | Done | API-backed with skeleton + empty states, cart FAB |
|
||||
| Shop tab — seller store | Done | Templates list, add/remove cart, template detail drilldown |
|
||||
| Template detail drilldown | Done | Full detail, cart/order actions |
|
||||
| Shopping cart (localStorage) | Done | Shared key with web checkout; cross-tab sync |
|
||||
| Cart overlay | Done | Quantity controls, remove, total, checkout link |
|
||||
| Web checkout handoff | Done | localStorage handoff; stock guard; socket guard |
|
||||
| Cart overlay | Done | Quantity controls, remove, total, in-shell checkout CTA |
|
||||
| In-shell checkout | Done | 3-step cart→address→payment; replaces web handoff |
|
||||
| In-shell payment view | Done | Direct balance intent + polling; checkout-flow back-nav |
|
||||
| Requests list | Done | API-backed with skeleton + empty states |
|
||||
| Request detail + stepper | Done | Status timeline, budget, dates with fa-IR locale |
|
||||
| New request form | Done | In-shell overlay, category fetch, validation |
|
||||
| Offer review in request detail | Done | Offers fetched via `useTelegramOffers`; accept/reject |
|
||||
| New request form | Done | In-shell overlay, category fetch, validation, Assist CTA |
|
||||
| Chat list | Done | API-backed conversation list + support row |
|
||||
| Chat thread | Done | Messages + optimistic send + Socket.IO real-time |
|
||||
| Account tab | Done | Profile, preferences, help, web-dashboard links, sign-out |
|
||||
| Direct seller chat | Done | `createConversation` from request detail |
|
||||
| Account tab | Done | Profile, preferences, help, sign-out |
|
||||
| Settings overlay | Done | In-shell profile editing |
|
||||
| Addresses overlay | Done | In-shell address management; reachable from checkout |
|
||||
| Points overlay | Done | In-shell points/loyalty |
|
||||
| Notifications overlay | Done | API-backed; Socket.IO real-time; mark-all-read |
|
||||
| Telegram chrome (MainButton / BackButton) | Done | Saffron palette, lifecycle hooks |
|
||||
| Notifications unread badge | Done | Bell icon in header |
|
||||
| Telegram chrome (BackButton) | Done | Full back-stack with checkout flow awareness |
|
||||
| Telegram MainButton | Disabled | Intentionally hidden (`isReady: false`); hook retained |
|
||||
| Haptic feedback | Done | All tap interactions |
|
||||
| Safe area insets | Done | Normalised from SDK + CSS env() fallback |
|
||||
| Deep link `startapp` context | Partial | Parsed but not yet used to auto-navigate to a request |
|
||||
| Bilingual onboarding sheet | Done | Shown on `isNewUser` flag |
|
||||
| Unsupported / browser fallback | Done | Web dashboard link |
|
||||
| amanat-assist integration | Done | "Open Assist" CTA in Home + New Request; window.location hand-off with access_token |
|
||||
| Deep link `startapp` routing | Partial | `startParam` parsed; auto-navigation to specific request not yet wired |
|
||||
| Backend room-scoped Socket.IO | Partial | Global socket broadcast fixed client-side (v2.8.4); server-side room scoping is a follow-up |
|
||||
| Client matrix QA (iOS/Android/Desktop) | Pending | Needs cross-platform testing pass |
|
||||
|
||||
### Open Items
|
||||
|
||||
- `startapp` deep link routing: if `context.startParam` matches `req_<id>`, auto-open `TelegramRequestDetailView` on first render.
|
||||
- Backend room-scoped Socket.IO for real-time chat updates (global socket event broadcast was fixed client-side in v2.8.4; server-side scoping is a follow-up).
|
||||
1. **`startapp` deep link routing:** if `context.startParam` matches `req_<id>`, auto-open `TelegramRequestDetailView` on first render.
|
||||
2. **Backend room-scoped Socket.IO:** server-side scoping for real-time chat updates (follow-up from client-side fix in v2.8.4).
|
||||
3. **Client matrix QA:** iOS Telegram, Android Telegram, Telegram Desktop, and web clients all need a full feature pass.
|
||||
4. **Review prompt:** `TelegramReviewPrompt` component exists but integration point (post-payment / post-delivery) is TBD.
|
||||
5. **Archived chats:** `TelegramArchivedChatsView` exists but is not yet surfaced in the navigation.
|
||||
|
||||
---
|
||||
|
||||
## 16. Related Documents
|
||||
## 17. Related Documents
|
||||
|
||||
- [[amanat-assist]] — the separate AI-driven Mini App for LLM-assisted request creation
|
||||
- [[PRD - Telegram Mini App Bilingual (EN + FA)]] — bilingual string inventory and RTL layout spec
|
||||
- [[PRD - Telegram Phone Number Authentication]] — phone-number auth as a future sign-in path
|
||||
- [[Authentication Flow]] — JWT lifecycle shared with the Mini App auth
|
||||
- [[Purchase Request Flow]] — escrow state machine surfaced in the stepper
|
||||
- [[Chat Flow]] — real-time messaging that the Mini App embeds
|
||||
- [[Request Template Checkout]] — web checkout flow that the Mini App cart hands off to
|
||||
- [[Request Template Checkout]] — web checkout flow; the Mini App now has its own in-shell checkout, but the localStorage cart key is shared
|
||||
|
||||
Reference in New Issue
Block a user