docs: Telegram Mini App pass 2 — shop/cart/account parity + frontend arch (v2.8.59)
- 04 - Flows/Telegram Mini App.md: major expansion — TelegramSellerShopView, TelegramCartView, TelegramAccountView, useTelegramCart/useTelegramShops hooks, full nav model, SDK surface table, shop→cart→checkout handoff flow - 01 - Architecture/Frontend Architecture.md: add Telegram Mini App section, TON Connect dependency, update to v2.8.59 - 09 - Audits/Activity Log.md: new entry for frontend@9bafbbb (v2.8.57–2.8.59) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,14 +2,15 @@
|
|||||||
title: Frontend Architecture
|
title: Frontend Architecture
|
||||||
tags: [architecture, frontend, nextjs]
|
tags: [architecture, frontend, nextjs]
|
||||||
created: 2026-05-23
|
created: 2026-05-23
|
||||||
|
updated: 2026-06-03
|
||||||
---
|
---
|
||||||
|
|
||||||
# Frontend Architecture
|
# Frontend Architecture
|
||||||
|
|
||||||
Module-level architecture of the Next.js 16 (App Router) + TypeScript + MUI v7 frontend. The current integration worktree observed locally is on `integrate-main-into-development`.
|
Module-level architecture of the Next.js 16 (App Router) + TypeScript + MUI v9 frontend. The current integration worktree observed locally is on `integrate-main-into-development`.
|
||||||
|
|
||||||
> [!info]
|
> [!info]
|
||||||
> Repo: `git@git.manko.yoga:222/nick/frontend.git` · Active integration branch observed locally: `integrate-main-into-development` · Version: 2.7.19 (`package.json`) · Dev port `3000`, Docker port `8083`.
|
> Repo: `git@git.manko.yoga:222/nick/frontend.git` · Active integration branch observed locally: `integrate-main-into-development` · Version: 2.8.59 (`package.json`) · Dev port `3000`, Docker port `8083`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -36,12 +37,17 @@ frontend/src/
|
|||||||
│ │ ├── post/ # Admin blog editor
|
│ │ ├── post/ # Admin blog editor
|
||||||
│ │ ├── shop-settings/ # Seller shop config
|
│ │ ├── shop-settings/ # Seller shop config
|
||||||
│ │ └── shops/ # Browse / checkout (dashboard scope)
|
│ │ └── shops/ # Browse / checkout (dashboard scope)
|
||||||
|
│ ├── telegram/ # Telegram Mini App shell (see §19)
|
||||||
|
│ │ ├── layout.tsx # TMA root — TonConnectUIProvider + minimal providers
|
||||||
|
│ │ ├── shop/ # Seller list + product browsing
|
||||||
|
│ │ ├── cart/ # In-shell cart + checkout handoff
|
||||||
|
│ │ └── account/ # Account tab (dashboard parity)
|
||||||
│ ├── error/ # Global error page
|
│ ├── error/ # Global error page
|
||||||
│ └── not-found.tsx # 404
|
│ └── not-found.tsx # 404
|
||||||
├── sections/ # Page-specific composition modules (one folder per feature)
|
├── sections/ # Page-specific composition modules (one folder per feature)
|
||||||
│ └── (chat|payment|request|request-template|dispute|user|points|...)
|
│ └── (chat|payment|request|request-template|dispute|user|points|telegram|...)
|
||||||
├── components/ # Reusable UI primitives (hook-form, table, upload, editor, ...)
|
├── components/ # Reusable UI primitives (hook-form, table, upload, editor, ...)
|
||||||
├── layouts/ # Page-template wrappers (auth-centered, auth-split, dashboard, main)
|
├── layouts/ # Page-template wrappers (auth-centered, auth-split, dashboard, main, telegram)
|
||||||
├── theme/ # MUI theme creation, palette, typography, overrides
|
├── theme/ # MUI theme creation, palette, typography, overrides
|
||||||
├── settings/ # Settings drawer (mode, layout, direction, color, font)
|
├── settings/ # Settings drawer (mode, layout, direction, color, font)
|
||||||
├── contexts/ # React Context providers (socket-context)
|
├── contexts/ # React Context providers (socket-context)
|
||||||
@@ -80,6 +86,8 @@ flowchart TB
|
|||||||
|
|
||||||
Order matters: theme must wrap query (because mutations show snackbars styled by theme); socket wraps snackbar (so socket-driven notifications can fire snackbars).
|
Order matters: theme must wrap query (because mutations show snackbars styled by theme); socket wraps snackbar (so socket-driven notifications can fire snackbars).
|
||||||
|
|
||||||
|
The Telegram Mini App shell (`app/telegram/`) uses its own slimmer layout that replaces the dashboard shell with `TonConnectUIProvider` and skips the settings drawer (see §19).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Route layout & guards
|
## 4. Route layout & guards
|
||||||
@@ -92,8 +100,9 @@ Order matters: theme must wrap query (because mutations show snackbars styled by
|
|||||||
| `dashboard/user/*` | dashboard | + `role: admin` |
|
| `dashboard/user/*` | dashboard | + `role: admin` |
|
||||||
| `dashboard/post/*` (editor) | dashboard | + `role: admin` |
|
| `dashboard/post/*` (editor) | dashboard | + `role: admin` |
|
||||||
| `dashboard/shop-settings/*` | dashboard | + `role: seller` |
|
| `dashboard/shop-settings/*` | dashboard | + `role: seller` |
|
||||||
|
| `telegram/*` | `layouts/telegram` (bottom-tab shell) | Telegram `initData` token guard + role check |
|
||||||
|
|
||||||
Guards live in `frontend/src/auth/` (HOC + hook). They consult the JWT-derived user context and redirect unauthenticated to `/auth/jwt/sign-in?returnTo=...`.
|
Guards live in `frontend/src/auth/` (HOC + hook). They consult the JWT-derived user context and redirect unauthenticated to `/auth/jwt/sign-in?returnTo=...`. The Telegram guard additionally validates `window.Telegram.WebApp.initData` before issuing a session.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -189,6 +198,8 @@ Higher-level hooks build on this:
|
|||||||
| `use-marketplace-socket` | broad market events |
|
| `use-marketplace-socket` | broad market events |
|
||||||
| `use-unified-real-time` | multi-event aggregator |
|
| `use-unified-real-time` | multi-event aggregator |
|
||||||
|
|
||||||
|
The Telegram Mini App shell reuses the same `SocketProvider` — live socket updates are available in the TMA shop, cart, and account tabs.
|
||||||
|
|
||||||
See [[Real-time Layer]] for the full event catalog.
|
See [[Real-time Layer]] for the full event catalog.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -213,6 +224,8 @@ const config = createConfig({
|
|||||||
|
|
||||||
Wallet UI: connect / disconnect / show address / show balance via `use-web3-wagmi`, `use-web3-context`. The current checkout target is the Request Network in-house flow; the DePay widget package remains legacy/frontier context and should not be treated as the primary path.
|
Wallet UI: connect / disconnect / show address / show balance via `use-web3-wagmi`, `use-web3-context`. The current checkout target is the Request Network in-house flow; the DePay widget package remains legacy/frontier context and should not be treated as the primary path.
|
||||||
|
|
||||||
|
TON wallet support is handled separately via `@ton/core` + `@tonconnect/ui-react` in the Telegram Mini App layer (see §19).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Internationalization
|
## 10. Internationalization
|
||||||
@@ -288,6 +301,9 @@ See [[Theme Configuration]] and [[Design System Overview]].
|
|||||||
|
|
||||||
State persists in `localStorage` under `settings-key`.
|
State persists in `localStorage` under `settings-key`.
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
> The Telegram Mini App shell does not render the settings drawer; theme and direction are inherited from the parent app's stored settings at launch.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Editor (TipTap)
|
## 14. Editor (TipTap)
|
||||||
@@ -350,6 +366,7 @@ See [[Docker Setup]], [[CI-CD Pipeline]], and [[Deployment]].
|
|||||||
| File | Why it matters |
|
| File | Why it matters |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `src/app/layout.tsx` | Provider tree |
|
| `src/app/layout.tsx` | Provider tree |
|
||||||
|
| `src/app/telegram/layout.tsx` | TMA shell — TonConnectUIProvider + slim provider tree |
|
||||||
| `src/lib/axios.ts` | Every HTTP call goes through this |
|
| `src/lib/axios.ts` | Every HTTP call goes through this |
|
||||||
| `src/contexts/socket-context.tsx` | Realtime plumbing |
|
| `src/contexts/socket-context.tsx` | Realtime plumbing |
|
||||||
| `src/theme/index.ts` | Theme creation entry |
|
| `src/theme/index.ts` | Theme creation entry |
|
||||||
@@ -359,6 +376,67 @@ See [[Docker Setup]], [[CI-CD Pipeline]], and [[Deployment]].
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 19. Telegram Mini App (TMA) layer
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
The app ships a dedicated Telegram Mini App shell at `app/telegram/`. It is served from the same Next.js process and Docker image as the main web app; no separate deployment is required. The Telegram bot registers the Mini App URL pointing at `/telegram`.
|
||||||
|
|
||||||
|
### Provider tree (TMA layout)
|
||||||
|
|
||||||
|
The TMA layout replaces the full dashboard shell with a minimal provider stack:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
A[TelegramLayout]
|
||||||
|
A --> B[AppRouterCacheProvider]
|
||||||
|
B --> C[ThemeProvider]
|
||||||
|
C --> D[QueryClientProvider]
|
||||||
|
D --> E[SocketProvider]
|
||||||
|
E --> F[TonConnectUIProvider<br/>manifestUrl: /tonconnect-manifest.json]
|
||||||
|
F --> G[SnackbarProvider]
|
||||||
|
G --> H[Children — telegram routes]
|
||||||
|
```
|
||||||
|
|
||||||
|
`TonConnectUIProvider` is the only addition relative to the web tree. Settings drawer, i18n provider, and auth guards are replaced by a Telegram `initData` token guard.
|
||||||
|
|
||||||
|
### Routes and features
|
||||||
|
|
||||||
|
| Route | Description |
|
||||||
|
|---|---|
|
||||||
|
| `telegram/shop` | Seller list with product browsing; infinite scroll |
|
||||||
|
| `telegram/shop/[seller]` | Single seller's catalogue |
|
||||||
|
| `telegram/cart` | In-shell shopping cart; checkout hands off to full web checkout URL |
|
||||||
|
| `telegram/account` | Account tab with dashboard parity: profile, wallet, order history |
|
||||||
|
|
||||||
|
### Authentication flow
|
||||||
|
|
||||||
|
1. Telegram injects `window.Telegram.WebApp.initData` on launch.
|
||||||
|
2. The TMA guard sends `initData` to `/api/auth/telegram` for HMAC verification.
|
||||||
|
3. On success the backend issues a short-lived JWT that the axios instance attaches as `Bearer`.
|
||||||
|
4. Role-based access (seller vs buyer views) is honoured via the same guard mechanism used in the dashboard.
|
||||||
|
|
||||||
|
### Real-time
|
||||||
|
|
||||||
|
`SocketProvider` is reused unchanged. The TMA shop, cart, and account tabs receive live socket updates (new messages, payment status, cart changes) on the same room infrastructure as the web dashboard.
|
||||||
|
|
||||||
|
### TON Connect (Telegram Wallet)
|
||||||
|
|
||||||
|
**Dependencies added**: `@ton/core`, `@tonconnect/ui-react`.
|
||||||
|
|
||||||
|
`TonConnectUIProvider` wraps the TMA routes and exposes a `useTonConnectUI()` hook. The manifest at `public/tonconnect-manifest.json` declares the app identity to the TON Connect protocol.
|
||||||
|
|
||||||
|
Current status: the wallet connection UI is in place (connect / disconnect / show address). **Actual TON payment processing is not yet wired to the backend** — the provider is pre-positioned for a future TON payment rail on the escrow platform. When that rail is built, the checkout handoff in `telegram/cart` will be extended to emit a TON transaction instead of redirecting to the web checkout.
|
||||||
|
|
||||||
|
### Constraints and differences from web
|
||||||
|
|
||||||
|
- No settings drawer (theme follows web localStorage, defaults to light/ltr).
|
||||||
|
- No TipTap editor or file-upload dropzone in TMA routes.
|
||||||
|
- `@mui/x-date-pickers` and DataGrid are not loaded in the TMA bundle.
|
||||||
|
- COOP/COEP headers required for WalletConnect popups are relaxed for TMA routes because Telegram's WebView does not support `SharedArrayBuffer`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[System Architecture]] — bird's-eye topology
|
- [[System Architecture]] — bird's-eye topology
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Telegram Mini App Flow
|
title: Telegram Mini App Flow
|
||||||
tags: [flow, telegram, mini-app, auth, bilingual, RTL]
|
tags: [flow, telegram, mini-app, auth, bilingual, RTL, shop, cart]
|
||||||
related_models: ["[[User]]"]
|
related_models: ["[[User]]"]
|
||||||
related_apis: ["POST /api/auth/telegram", "[[Auth API]]"]
|
related_apis: ["POST /api/auth/telegram", "[[Auth API]]"]
|
||||||
task: "5.4"
|
task: "5.4"
|
||||||
@@ -8,12 +8,12 @@ task: "5.4"
|
|||||||
|
|
||||||
> **Last updated:** 2026-06-03
|
> **Last updated:** 2026-06-03
|
||||||
> **Status:** IN PROGRESS — Task 5.4 (dependencies: 5.1 auth infra, 5.2 Telegram sign-in endpoint)
|
> **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.44
|
> **Frontend branch:** `integrate-main-into-development` · v2.8.59
|
||||||
> **Entry point:** `src/sections/telegram/` · route `/telegram`
|
> **Entry point:** `src/sections/telegram/` · route `/telegram`
|
||||||
|
|
||||||
# Telegram Mini App Flow
|
# 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, review offer state, follow payments, and message each other without leaving Telegram.
|
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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -29,19 +29,23 @@ Telegram Client
|
|||||||
├─ useTelegramMainButton ← native chrome sync
|
├─ useTelegramMainButton ← native chrome sync
|
||||||
├─ useTelegramBackButton ← native chrome sync
|
├─ useTelegramBackButton ← native chrome sync
|
||||||
├─ useTelegramHaptic ← haptic wrapper
|
├─ useTelegramHaptic ← haptic wrapper
|
||||||
|
├─ useTelegramCart ← shared localStorage cart
|
||||||
│
|
│
|
||||||
├─ [state: loading] → TelegramLoadingState
|
├─ [state: loading] → TelegramLoadingState
|
||||||
├─ [state: unsupported] → TelegramUnsupportedState
|
├─ [state: unsupported] → TelegramUnsupportedState
|
||||||
├─ [state: unlinked] → TelegramUnlinkedState
|
├─ [state: unlinked] → TelegramUnlinkedState
|
||||||
└─ [state: linked]
|
└─ [state: linked]
|
||||||
├─ TelegramHeader
|
├─ TelegramHeader
|
||||||
├─ TelegramTabBar (Home / Requests / Chat / Account)
|
├─ TelegramTabBar (Home / Shop / Requests / Chat / Account)
|
||||||
│
|
│
|
||||||
├─ TelegramHomeView
|
├─ TelegramHomeView
|
||||||
|
├─ TelegramShopView → TelegramSellerShopView
|
||||||
├─ TelegramRequestsView → TelegramRequestDetailView
|
├─ TelegramRequestsView → TelegramRequestDetailView
|
||||||
├─ TelegramChatView → TelegramChatThreadView
|
├─ TelegramChatView → TelegramChatThreadView
|
||||||
├─ TelegramAccountView
|
├─ TelegramAccountView
|
||||||
└─ [overlay] TelegramNewRequestView
|
└─ [overlay] TelegramNewRequestView
|
||||||
|
└─ [overlay] TelegramNotificationsView
|
||||||
|
└─ [overlay] TelegramCartView
|
||||||
```
|
```
|
||||||
|
|
||||||
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 only used as a final escape hatch to the full web dashboard.
|
||||||
@@ -143,20 +147,24 @@ When `initData` is absent (accessed via a path that skips Telegram context), onl
|
|||||||
All navigation is in-shell React state — no Next.js router is involved.
|
All navigation is in-shell React state — no Next.js router is involved.
|
||||||
|
|
||||||
```
|
```
|
||||||
activeTab : 'home' | 'requests' | 'chat' | 'account'
|
activeTab : 'home' | 'shop' | 'requests' | 'chat' | 'account'
|
||||||
overlayScreen : 'new-request' | null
|
overlayScreen : 'new-request' | 'notifications' | 'cart' | null
|
||||||
openConversationId : string | null
|
openConversationId : string | null
|
||||||
openRequestId : string | null
|
openRequestId : string | null
|
||||||
|
openSellerId : string | null
|
||||||
```
|
```
|
||||||
|
|
||||||
**Priority rendering** (first match wins):
|
**Priority rendering** (first match wins):
|
||||||
|
|
||||||
1. `openConversationId` → `TelegramChatThreadView`
|
1. `openConversationId` → `TelegramChatThreadView`
|
||||||
2. `openRequestId` → `TelegramRequestDetailView`
|
2. `openRequestId` → `TelegramRequestDetailView`
|
||||||
3. `overlayScreen === 'new-request'` → `TelegramNewRequestView`
|
3. `openSellerId` → `TelegramSellerShopView`
|
||||||
4. `activeTab` → appropriate tab view
|
4. `overlayScreen === 'cart'` → `TelegramCartView`
|
||||||
|
5. `overlayScreen === 'notifications'` → `TelegramNotificationsView`
|
||||||
|
6. `overlayScreen === 'new-request'` → `TelegramNewRequestView`
|
||||||
|
7. `activeTab` → appropriate tab view
|
||||||
|
|
||||||
**Back button** (Telegram native `BackButton`) dismisses in reverse priority order: chat thread → request detail → overlay → returns to `home` tab.
|
**Back button** (Telegram native `BackButton`) dismisses in reverse priority order: chat thread → request detail → seller shop → overlay → returns to `home` tab.
|
||||||
|
|
||||||
`BackButton` visibility: shown whenever `state === 'linked'` and either an overlay/drilldown is active, or `activeTab !== 'home'`.
|
`BackButton` visibility: shown whenever `state === 'linked'` and either an overlay/drilldown is active, or `activeTab !== 'home'`.
|
||||||
|
|
||||||
@@ -168,16 +176,89 @@ Both chrome buttons are styled with the amaneh saffron palette (`color: #C2410C`
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Supported Flows
|
## 7. Tab Structure
|
||||||
|
|
||||||
### 7.1 Browse Requests (Requests Tab)
|
The shell has **five bottom tabs** rendered by `TelegramTabBar`:
|
||||||
|
|
||||||
- `TelegramRequestsView` fetches the user's purchase requests via `useTelegramMyRequests` (GET `/api/purchase-requests/my`).
|
| Tab | Icon | View | Purpose |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Home | house | `TelegramHomeView` | Welcome banner, quick-action cards, escrow-state chips |
|
||||||
|
| Shop | storefront | `TelegramShopView` | Sellers list; drill into seller store; add templates to cart |
|
||||||
|
| Requests | list | `TelegramRequestsView` | User's escrow requests with status stepper |
|
||||||
|
| Chat | speech bubble | `TelegramChatView` | Conversation list + support entry |
|
||||||
|
| Account | person | `TelegramAccountView` | Profile, preferences, links to web dashboard sections |
|
||||||
|
|
||||||
|
`handleTabSelect` clears all overlays and drill-down IDs before switching tab.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Supported Flows
|
||||||
|
|
||||||
|
### 8.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.
|
||||||
|
|
||||||
|
### 8.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'`.
|
||||||
|
- Tap a seller row → sets `openSellerId` → navigates to `TelegramSellerShopView`.
|
||||||
|
|
||||||
|
### 8.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).
|
||||||
|
- Floating "Cart · N templates" sticky button at bottom when `totalItems > 0`; tap calls `onOpenCart()`.
|
||||||
|
|
||||||
|
### 8.4 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.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
Destination: `/dashboard/shops/checkout` — `RequestTemplateCheckoutView` wrapped by `RequestTemplateCheckoutProvider`.
|
||||||
|
|
||||||
|
The provider reads the shared `localStorage` key and hydrates the TMA cart. The checkout is a 3-step stepper:
|
||||||
|
|
||||||
|
| 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 |
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
- `TelegramRequestsView` fetches the user's purchase requests via `useTelegramMyRequests` (GET `/api/requests`).
|
||||||
- Displays a skeleton loader, then a scrollable list of `TelegramRequestRow` items.
|
- Displays a skeleton loader, then a scrollable list of `TelegramRequestRow` items.
|
||||||
- Each row shows: title, status chip, budget, creation date.
|
- Each row shows: title, status chip, budget, creation date.
|
||||||
- Tap → sets `openRequestId` → renders `TelegramRequestDetailView`.
|
- Tap → sets `openRequestId` → renders `TelegramRequestDetailView`.
|
||||||
|
|
||||||
### 7.2 Request Detail with Stepper
|
### 8.7 Request Detail with Stepper
|
||||||
|
|
||||||
- `TelegramRequestDetailView` fetches a single request via `useTelegramRequest`.
|
- `TelegramRequestDetailView` fetches a single request via `useTelegramRequest`.
|
||||||
- Renders `TelegramRequestStepper` — a visual timeline of the escrow status flow from `pending_payment` → `completed`.
|
- Renders `TelegramRequestStepper` — a visual timeline of the escrow status flow from `pending_payment` → `completed`.
|
||||||
@@ -185,7 +266,7 @@ Both chrome buttons are styled with the amaneh saffron palette (`color: #C2410C`
|
|||||||
- Also renders: budget, description, creation date, category, urgency.
|
- Also renders: budget, description, creation date, category, urgency.
|
||||||
- Dates formatted via `toLocaleDateString` with `fa-IR` locale for Persian.
|
- Dates formatted via `toLocaleDateString` with `fa-IR` locale for Persian.
|
||||||
|
|
||||||
### 7.3 Create New Request
|
### 8.8 Create New Request
|
||||||
|
|
||||||
- `TelegramNewRequestView` is a full-screen overlay (not a routed page).
|
- `TelegramNewRequestView` is a full-screen overlay (not a routed page).
|
||||||
- Form fields: title, description, category (fetched from `/api/categories`), budget min/max, urgency.
|
- Form fields: title, description, category (fetched from `/api/categories`), budget min/max, urgency.
|
||||||
@@ -193,27 +274,79 @@ Both chrome buttons are styled with the amaneh saffron palette (`color: #C2410C`
|
|||||||
- On success: closes overlay, switches `activeTab` to `'requests'`.
|
- On success: closes overlay, switches `activeTab` to `'requests'`.
|
||||||
- `MainButton` is hidden while the overlay is open (submit lives in the form itself).
|
- `MainButton` is hidden while the overlay is open (submit lives in the form itself).
|
||||||
|
|
||||||
### 7.4 Chat
|
### 8.9 Chat Tab
|
||||||
|
|
||||||
- `TelegramChatView` shows the user's active conversations via `useTelegramConversations`.
|
- `TelegramChatView` shows the user's active conversations via `useTelegramConversations`.
|
||||||
- Tap a row → sets `openConversationId` → renders `TelegramChatThreadView`.
|
- Includes a Support row that calls `createSupportChat()` → `POST /api/chat/support`, then opens `TelegramChatThreadView` with the returned conversation ID.
|
||||||
|
- Tap a conversation row → sets `openConversationId` → renders `TelegramChatThreadView`.
|
||||||
- `TelegramChatThreadView` loads messages via `useTelegramChatThread`, renders `TelegramChatBubble` items, and includes `TelegramChatComposer` for sending.
|
- `TelegramChatThreadView` loads messages via `useTelegramChatThread`, renders `TelegramChatBubble` items, and includes `TelegramChatComposer` for sending.
|
||||||
- Optimistic send: message appears immediately, confirmed/rolled back on API response.
|
- 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.
|
||||||
|
|
||||||
### 7.5 Account
|
### 8.10 Account Tab
|
||||||
|
|
||||||
- `TelegramAccountView` shows profile info (name, email, Telegram username, `telegramVerified` status), linked wallet (if any), and notification preferences.
|
**`TelegramAccountView`** (`telegram-account-view.tsx`):
|
||||||
- Contains sign-out action and language toggle.
|
|
||||||
|
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).
|
||||||
|
- Notifications → opens `TelegramNotificationsView` overlay in-shell.
|
||||||
|
- Addresses → `/dashboard/account/address` (web).
|
||||||
|
- Passkey → `/dashboard/account/passkey` (web).
|
||||||
|
|
||||||
|
**Help section:**
|
||||||
|
- Support → `createSupportChat()` → opens `TelegramChatThreadView` in-shell.
|
||||||
|
- Terms & Conditions → placeholder, "coming soon".
|
||||||
|
|
||||||
|
**Session section:**
|
||||||
|
- Sign Out → `TelegramBottomSheet` confirmation dialog → `authSignOut()` + `window.location.assign(paths.auth.jwt.signIn)`.
|
||||||
|
|
||||||
|
### 8.11 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`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Bilingual Support (EN / FA)
|
## 9. API Calls
|
||||||
|
|
||||||
|
| Action | Hook / call | Backend endpoint |
|
||||||
|
|---|---|---|
|
||||||
|
| Auto sign-in | `useTelegramAutoSignIn` → `signInWithTelegram({initData})` | `POST /api/auth/telegram` |
|
||||||
|
| Sellers list | `useTelegramShops` → `getTemplateSellers()` | `GET /api/request-templates/sellers` |
|
||||||
|
| Seller + templates | `useTelegramSellerShop` → `getSellerWithTemplates(id)` | `GET /api/request-templates/sellers/:id` |
|
||||||
|
| Marketplace sellers | `useTelegramSellers` → `getSellers()` | `GET /api/marketplace/sellers` |
|
||||||
|
| My requests | `useTelegramMyRequests` | `GET /api/requests` |
|
||||||
|
| Single request | `useTelegramRequest` | `GET /api/purchase-requests/:id` |
|
||||||
|
| Create request | shell → `createPurchaseRequest()` | `POST /api/purchase-requests` |
|
||||||
|
| Conversations | `useTelegramConversations` | `GET /api/chat/conversations` |
|
||||||
|
| Chat thread | `useTelegramChatThread` | `GET /api/chat/:id` + Socket.IO real-time |
|
||||||
|
| Support chat | `createSupportChat()` | `POST /api/chat/support` |
|
||||||
|
| 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 |
|
||||||
|
|
||||||
|
Cart operations (add/remove/quantity) are **pure localStorage** — no API calls until web checkout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Bilingual Support (EN / FA)
|
||||||
|
|
||||||
**Language detection priority** (`useTelegramLanguage`):
|
**Language detection priority** (`useTelegramLanguage`):
|
||||||
|
|
||||||
1. `localStorage` key `amn_tg_lang` — user's persisted manual selection.
|
1. `?lang=` URL query param — dev preview override.
|
||||||
2. `initDataUnsafe.user.language_code` — Telegram-reported language (`"fa"` or `"fa-IR"` → Persian).
|
2. `localStorage` key `amn_tg_lang` — user's persisted manual selection.
|
||||||
3. Fallback → English.
|
3. `initDataUnsafe.user.language_code` — Telegram-reported language (`"fa"` or `"fa-IR"` → Persian).
|
||||||
|
4. Fallback → English.
|
||||||
|
|
||||||
**Language toggle:** `TelegramLanguageToggle` in the header — two buttons `[ EN | فا ]`. On tap: haptic light + language switch + persist to `localStorage`.
|
**Language toggle:** `TelegramLanguageToggle` in the header — two buttons `[ EN | فا ]`. On tap: haptic light + language switch + persist to `localStorage`.
|
||||||
|
|
||||||
@@ -226,6 +359,7 @@ Both chrome buttons are styled with the amaneh saffron palette (`color: #C2410C`
|
|||||||
| Arrow icons | `→` | `←` |
|
| Arrow icons | `→` | `←` |
|
||||||
| Text alignment | left | right (inherits from `dir`) |
|
| Text alignment | left | right (inherits from `dir`) |
|
||||||
| Chip list wrap | left-to-right | right-to-left |
|
| Chip list wrap | left-to-right | right-to-left |
|
||||||
|
| Amounts | always `dir="ltr"` | always `dir="ltr"` |
|
||||||
|
|
||||||
Font size bumps for Persian: body 13 px → 14 px, labels 10 px → 11 px (Vazirmatn renders optically smaller).
|
Font size bumps for Persian: body 13 px → 14 px, labels 10 px → 11 px (Vazirmatn renders optically smaller).
|
||||||
|
|
||||||
@@ -234,7 +368,7 @@ Font size bumps for Persian: body 13 px → 14 px, labels 10 px → 11 px (Vazir
|
|||||||
```ts
|
```ts
|
||||||
// src/sections/telegram/locales/en.ts + fa.ts
|
// src/sections/telegram/locales/en.ts + fa.ts
|
||||||
const TR = {
|
const TR = {
|
||||||
en: { loading, unsupported, unlinked, header, home, requests,
|
en: { loading, unsupported, unlinked, header, home, shop, requests,
|
||||||
chat, account, newRequest, tabs, main, onboarding, errors, displayName, dir },
|
chat, account, newRequest, tabs, main, onboarding, errors, displayName, dir },
|
||||||
fa: { /* same keys, Farsi strings, dir: 'rtl' */ },
|
fa: { /* same keys, Farsi strings, dir: 'rtl' */ },
|
||||||
};
|
};
|
||||||
@@ -244,7 +378,7 @@ All JSX uses `t.<section>.<key>` — no inline strings in components.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Design System
|
## 11. Design System
|
||||||
|
|
||||||
**File:** `src/sections/telegram/constants.ts` · `src/sections/telegram/telegram-shell-css.ts`
|
**File:** `src/sections/telegram/constants.ts` · `src/sections/telegram/telegram-shell-css.ts`
|
||||||
|
|
||||||
@@ -271,9 +405,9 @@ The Mini App has a distinct visual identity (cream/saffron Persian palette) that
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Telegram SDK Usage Patterns
|
## 12. Telegram SDK Usage Patterns
|
||||||
|
|
||||||
### 10.1 Safe-Area Inset
|
### 12.1 Safe-Area Inset
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// TelegramContext.safeArea = { top, right, bottom, left } (px)
|
// TelegramContext.safeArea = { top, right, bottom, left } (px)
|
||||||
@@ -284,7 +418,7 @@ 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.
|
All views receive `topInset` / `bottomInset` props and add them as explicit `paddingTop` / `paddingBottom` to avoid content being obscured by the Telegram chrome.
|
||||||
|
|
||||||
### 10.2 Haptic Feedback
|
### 12.2 Haptic Feedback
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// useTelegramHaptic(webApp) → haptic('light' | 'medium')
|
// useTelegramHaptic(webApp) → haptic('light' | 'medium')
|
||||||
@@ -293,7 +427,7 @@ 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). All calls are wrapped in try/catch — the API may be absent on older clients.
|
||||||
|
|
||||||
### 10.3 Back Button
|
### 12.3 Back Button
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
useTelegramBackButton({ webApp, isVisible, onClick })
|
useTelegramBackButton({ webApp, isVisible, onClick })
|
||||||
@@ -301,7 +435,7 @@ useTelegramBackButton({ webApp, isVisible, onClick })
|
|||||||
// Cleanup: offClick() on unmount / visibility change
|
// Cleanup: offClick() on unmount / visibility change
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10.4 Main Button
|
### 12.4 Main Button
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
useTelegramMainButton({ webApp, isReady, text, onClick })
|
useTelegramMainButton({ webApp, isReady, text, onClick })
|
||||||
@@ -310,13 +444,13 @@ useTelegramMainButton({ webApp, isReady, text, onClick })
|
|||||||
// setParams requires WebApp >= 6.1; silent fallback for older clients
|
// setParams requires WebApp >= 6.1; silent fallback for older clients
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10.5 Theme Integration
|
### 12.5 Theme Integration
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Edge Cases
|
## 13. Edge Cases
|
||||||
|
|
||||||
| Scenario | Detection | Handling |
|
| Scenario | Detection | Handling |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -331,10 +465,13 @@ Telegram's `themeParams` is normalised (both camelCase and snake_case accepted)
|
|||||||
| Old Telegram client (< 6.1) | `setParams` throws | Try/catch silences it; button shows without saffron colour |
|
| Old Telegram client (< 6.1) | `setParams` throws | Try/catch silences it; button shows without saffron colour |
|
||||||
| RTL + keyboard overlap | Viewport shrinks on soft keyboard open | `flex: 1` + `overflowY: auto` on content area; bottom safe-area inset on tab bar |
|
| RTL + keyboard overlap | Viewport shrinks on soft keyboard open | `flex: 1` + `overflowY: auto` on content area; bottom safe-area inset on tab bar |
|
||||||
| Persian locale date formatting | `lang === 'fa'` | `toLocaleDateString('fa-IR', ...)` in `formatDate` helper |
|
| 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 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. File Map
|
## 14. File Map
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
@@ -351,32 +488,42 @@ src/
|
|||||||
index.ts # getTelegramDict(lang)
|
index.ts # getTelegramDict(lang)
|
||||||
hooks/
|
hooks/
|
||||||
use-telegram-live-context.ts # SDK polling
|
use-telegram-live-context.ts # SDK polling
|
||||||
use-telegram-language.ts # EN/FA detection + localStorage persist
|
use-telegram-language.ts # EN/FA detection + ?lang= + localStorage persist
|
||||||
use-telegram-auto-sign-in.ts # initData → JWT exchange
|
use-telegram-auto-sign-in.ts # initData → JWT exchange
|
||||||
use-telegram-main-button.ts # MainButton lifecycle
|
use-telegram-main-button.ts # MainButton lifecycle
|
||||||
use-telegram-back-button.ts # BackButton lifecycle
|
use-telegram-back-button.ts # BackButton lifecycle
|
||||||
use-telegram-haptic.ts # HapticFeedback wrapper
|
use-telegram-haptic.ts # HapticFeedback wrapper
|
||||||
use-telegram-my-requests.ts # GET /api/purchase-requests/my
|
use-telegram-cart.ts # localStorage cart (shared with web checkout)
|
||||||
|
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-request.ts # GET /api/purchase-requests/:id
|
||||||
use-telegram-conversations.ts # Chat conversation list
|
use-telegram-conversations.ts # Chat conversation list
|
||||||
use-telegram-chat-thread.ts # Chat thread + optimistic send
|
use-telegram-chat-thread.ts # Chat thread + optimistic send
|
||||||
|
use-telegram-notifications.ts # GET /api/notifications
|
||||||
index.ts
|
index.ts
|
||||||
view/
|
view/
|
||||||
telegram-mini-app-view.tsx # Shell orchestrator (all state lives here)
|
telegram-mini-app-view.tsx # Shell orchestrator (all state lives here)
|
||||||
telegram-home-view.tsx # Home tab
|
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-cart-view.tsx # Cart overlay
|
||||||
telegram-requests-view.tsx # Requests list tab
|
telegram-requests-view.tsx # Requests list tab
|
||||||
telegram-request-detail-view.tsx # Request drilldown + stepper
|
telegram-request-detail-view.tsx # Request drilldown + stepper
|
||||||
telegram-new-request-view.tsx # New request overlay form
|
telegram-new-request-view.tsx # New request overlay form
|
||||||
telegram-chat-view.tsx # Chat conversation list tab
|
telegram-chat-view.tsx # Chat conversation list tab
|
||||||
telegram-chat-thread-view.tsx # Chat thread drilldown
|
telegram-chat-thread-view.tsx # Chat thread drilldown
|
||||||
telegram-account-view.tsx # Account + sign-out tab
|
telegram-account-view.tsx # Account + preferences + sign-out tab
|
||||||
|
telegram-notifications-view.tsx # Notifications overlay
|
||||||
index.ts
|
index.ts
|
||||||
components/
|
components/
|
||||||
telegram-header.tsx # AMN logo + subtitle + language toggle
|
telegram-header.tsx # AMN logo + subtitle + language toggle
|
||||||
telegram-tab-bar.tsx # Bottom tab bar (4 tabs)
|
telegram-tab-bar.tsx # Bottom tab bar (5 tabs)
|
||||||
telegram-welcome-banner.tsx # Home: escrow account banner + CTA
|
telegram-welcome-banner.tsx # Home: escrow account banner + CTA
|
||||||
telegram-quick-actions.tsx # Home: action cards (Requests / Payments / Chat)
|
telegram-quick-actions.tsx # Home: action cards (Requests / Payments / Chat)
|
||||||
telegram-escrow-state-chips.tsx # Home: status chip legend
|
telegram-escrow-state-chips.tsx # Home: status chip legend
|
||||||
|
telegram-shop-row.tsx # Shop: seller list row
|
||||||
telegram-request-row.tsx # Requests: list row
|
telegram-request-row.tsx # Requests: list row
|
||||||
telegram-request-stepper.tsx # Detail: visual escrow timeline
|
telegram-request-stepper.tsx # Detail: visual escrow timeline
|
||||||
telegram-list-row.tsx # Generic list row primitive
|
telegram-list-row.tsx # Generic list row primitive
|
||||||
@@ -399,7 +546,7 @@ src/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Current Implementation Status
|
## 15. Current Implementation Status (v2.8.59)
|
||||||
|
|
||||||
| Area | Status | Notes |
|
| Area | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -409,33 +556,39 @@ src/
|
|||||||
| Manual sign-in (unlinked) | Done | Email + create account fallbacks |
|
| Manual sign-in (unlinked) | Done | Email + create account fallbacks |
|
||||||
| Bilingual EN/FA | Done | Full string inventory, RTL layout, Vazirmatn font |
|
| Bilingual EN/FA | Done | Full string inventory, RTL layout, Vazirmatn font |
|
||||||
| Language toggle | Done | Header toggle + localStorage persist |
|
| 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 |
|
| 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 |
|
||||||
|
| 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 |
|
||||||
| Requests list | Done | API-backed with skeleton + empty states |
|
| Requests list | Done | API-backed with skeleton + empty states |
|
||||||
| Request detail + stepper | Done | Status timeline, budget, dates with fa-IR locale |
|
| Request detail + stepper | Done | Status timeline, budget, dates with fa-IR locale |
|
||||||
| New request form | Done | In-shell overlay, category fetch, validation |
|
| New request form | Done | In-shell overlay, category fetch, validation |
|
||||||
| Chat list | Done | API-backed conversation list |
|
| Chat list | Done | API-backed conversation list + support row |
|
||||||
| Chat thread | Done | Messages + optimistic send |
|
| Chat thread | Done | Messages + optimistic send + Socket.IO real-time |
|
||||||
| Account view | Done | Profile, wallet stub, sign-out |
|
| Account tab | Done | Profile, preferences, help, web-dashboard links, sign-out |
|
||||||
|
| Notifications overlay | Done | API-backed; Socket.IO real-time; mark-all-read |
|
||||||
| Telegram chrome (MainButton / BackButton) | Done | Saffron palette, lifecycle hooks |
|
| Telegram chrome (MainButton / BackButton) | Done | Saffron palette, lifecycle hooks |
|
||||||
| Haptic feedback | Done | All tap interactions |
|
| Haptic feedback | Done | All tap interactions |
|
||||||
| Safe area insets | Done | Normalised from SDK + CSS env() fallback |
|
| 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 |
|
| Deep link `startapp` context | Partial | Parsed but not yet used to auto-navigate to a request |
|
||||||
| Bilingual onboarding sheet | Done | Shown on `isNewUser` flag |
|
| Bilingual onboarding sheet | Done | Shown on `isNewUser` flag |
|
||||||
| Unsupported / browser fallback | Done | Web dashboard link |
|
| Unsupported / browser fallback | Done | Web dashboard link |
|
||||||
| Bilingual PRD (Task 5.4 scope) | IN PROGRESS | String extraction done; `?lang=fa` dev preview param pending |
|
|
||||||
|
|
||||||
### Open Items (Task 5.4)
|
### Open Items
|
||||||
|
|
||||||
- `?lang=fa` URL override for browser dev preview (one-line addition to `useTelegramLanguage`).
|
|
||||||
- `startapp` deep link routing: if `context.startParam` matches `req_<id>`, auto-open `TelegramRequestDetailView` on first render.
|
- `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).
|
- 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).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Related Documents
|
## 16. Related Documents
|
||||||
|
|
||||||
- [[PRD - Telegram Mini App Bilingual (EN + FA)]] — bilingual string inventory and RTL layout spec
|
- [[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
|
- [[PRD - Telegram Phone Number Authentication]] — phone-number auth as a future sign-in path
|
||||||
- [[Authentication Flow]] — JWT lifecycle shared with the Mini App auth
|
- [[Authentication Flow]] — JWT lifecycle shared with the Mini App auth
|
||||||
- [[Purchase Request Flow]] — escrow state machine surfaced in the stepper
|
- [[Purchase Request Flow]] — escrow state machine surfaced in the stepper
|
||||||
- [[Chat Flow]] — real-time messaging that the Mini App embeds
|
- [[Chat Flow]] — real-time messaging that the Mini App embeds
|
||||||
|
- [[Request Template Checkout]] — web checkout flow that the Mini App cart hands off to
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ entries on top. Maintained by agents per the rule in `../AGENTS.md`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 2026-06-03 — frontend@9bafbbb — Telegram Mini App: full in-shell shop, account tab parity, and shopping cart (v2.8.57–v2.8.59)
|
||||||
|
|
||||||
|
**Commits:** `a8ae1e3` (v2.8.57), `6dc3918` (v2.8.58), `9bafbbb` (v2.8.59) — frontend only; backend stays at v2.8.56
|
||||||
|
**Touched:** `telegram-mini-app-view.tsx` (shell nav: `openSellerId`, `overlayScreen='cart'`, BackButton dismissal chain), `telegram-shop-view.tsx` (cart badge header button, `TelegramShopRow` converted from `<a href>` to in-shell `onOpen`), `telegram-seller-shop-view.tsx` (new — seller header, active templates with budget/usage, add/remove-to-cart buttons, floating cart CTA), `telegram-cart-view.tsx` (new — qty stepper, remove, USDT total, "Continue to payment" → web checkout), `telegram-account-view.tsx` (new — profile header, preferences section, help section, sign-out with bottom-sheet confirm), `hooks/use-telegram-seller-shop.ts` (new — SWR over `getSellerWithTemplates`), `hooks/use-telegram-cart.ts` (new — localStorage `app-request-template-checkout`, custom `tg-cart-changed` event), `hooks/use-telegram-shops.ts` (new — SWR over `getTemplateSellers`), telegram locales (fa/en/types)
|
||||||
|
**Why:** Three sequential buyer-parity milestones shipped in one session. (1) v2.8.57: tapping a seller in فروشگاه previously opened the web dashboard inside the webview; the seller store now renders entirely in-shell with `TelegramSellerShopView` — seller header, active templates, budget/usage count — and template ordering hands off to the web from-template checkout where the wallet stack lives. (2) v2.8.58: the web account menu (تنظیمات عمومی، اعلانها، کیف پول، آدرسهای تحویل، Passkey) had no Mini App counterpart; all five are now accessible from the account tab — notifications open the existing in-shell overlay, the other four deep-link to web dashboard pages (labeled «در داشبورد وب باز میشود») because passkey and wallet require browser-context APIs unavailable in Telegram. (3) v2.8.59: phase 1 of full buyer parity — new `useTelegramCart` hook writes to the same localStorage key (`app-request-template-checkout`) that the web checkout provider reads, so the Mini App cart IS the web cart with no sync step; `TelegramCartView` adds qty controls, remove, and a "Continue to payment" link that hands off seamlessly. Remaining buyer-parity roadmap: offers view/accept on requests, delivery confirmation, payments list, points/referral, addresses CRUD, TON Connect payments (Telegram Wallet is TON-native; backend already has `tonProofService`).
|
||||||
|
**Verification:** tsc + eslint clean across all three commits. Admin verifies after deploy: (shop) فروشگاه → tap seller → in-shell shop → سفارش این قالب → web checkout; (cart) افزودن به سبد → cart badge → سبد overlay → ادامه و پرداخت → web checkout shows same items; (account) account tab → preferences rows → notifications overlay in-shell, remaining rows open web dashboard.
|
||||||
|
**Linked docs updated:** `04 - Flows/Telegram Mini App.md` (major update — navigation model, all view files, shop/cart/checkout flow, account tab, SDK surfaces, API call table), `01 - Architecture/Frontend Architecture.md` (updated — Telegram Mini App section)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 2026-06-02 — backend@cf59726, frontend@a2b972b — normalize Postgres repository store modes
|
### 2026-06-02 — backend@cf59726, frontend@a2b972b — normalize Postgres repository store modes
|
||||||
|
|
||||||
**Commits:** backend `cf59726` (version `2.8.37`), frontend `a2b972b` (version `2.8.37`)
|
**Commits:** backend `cf59726` (version `2.8.37`), frontend `a2b972b` (version `2.8.37`)
|
||||||
|
|||||||
Reference in New Issue
Block a user