# BAGIAN 3: FLOWCHART FRONTEND (FE)
## Detailed Frontend Application Flowcharts

---

## 3.1 FE General Routing Architecture

Diagram lengkap struktur routing Frontend dari root hingga setiap halaman.

```mermaid
flowchart TD
    ROOT["/ (Root Route)<br/>src/app.tsx"] --> MAIN_LAYOUT["MainLayout<br/>(Public Pages)"]
    ROOT --> AUTH_LAYOUT["AuthSplitLayout<br/>(Auth Pages)"]
    ROOT --> SIMPLE_LAYOUT["SimpleLayout<br/>(Minimal Pages)"]
    ROOT --> DASH_LAYOUT["DashboardLayout<br/>(Protected Pages)"]

    subgraph PUBLIC["Public Routes"]
        MAIN_LAYOUT --> HOME["/ — HomePage"]
        MAIN_LAYOUT --> ABOUT["/about-us"]
        MAIN_LAYOUT --> PRIVACY["/privacy-policy"]
        MAIN_LAYOUT --> TERMS["/terms-of-service"]

        SIMPLE_LAYOUT --> MAINT["/maintenance"]
    end

    subgraph AUTH_ROUTES["Auth Routes (GuestGuard)"]
        AUTH_LAYOUT --> GUEST["GuestGuard<br/>(Block if logged in)"]
        GUEST --> SIGNIN["/auth/sign-in<br/>BetterAuth.SignInPage"]
        GUEST --> FORGOT["/auth/forgot-password<br/>BetterAuth.ForgotPasswordPage"]
        GUEST --> RESET["/auth/reset-password<br/>BetterAuth.ResetPasswordPage"]
        GUEST --> SIGNUP["/auth/sign-up<br/>(Hidden - Invite Only)"]
        GUEST --> ACCEPT_INV["/accept-invitation/:id<br/>(+ ReCAPTCHA)"]
    end

    subgraph ERROR_ROUTES["Error Routes"]
        ROOT --> E403["/error/403 — Forbidden"]
        ROOT --> E404["/error/404 — Not Found"]
        ROOT --> E500["/error/500 — Server Error"]
    end

    subgraph DASH["Dashboard Routes (AuthGuard + WorkspaceGuard)"]
        DASH_LAYOUT --> AUTH_G["AuthGuard<br/>Check Session"]
        AUTH_G --> WS_G["WorkspaceGuard<br/>Check Active Workspace"]
        WS_G --> DASH_NAV{{"Dashboard Navigation"}}

        DASH_NAV --> CHAT_R["/dashboard/chat"]
        DASH_NAV --> SOCIAL["/dashboard/social-media"]
        DASH_NAV --> WS_CREATE["/dashboard/workspace/create"]
        DASH_NAV --> TAG_NAV["/dashboard/tag<br/>/new /:id/edit"]
        DASH_NAV --> CONTACT["/dashboard/contact"]
        DASH_NAV --> CAMP_NAV["/dashboard/campaign/*"]
        DASH_NAV --> TICK_NAV["/dashboard/ticket/*"]
        DASH_NAV --> SET_NAV["/dashboard/settings/*"]
    end

    style ROOT fill:#C8E6C9,stroke:#4CAF50
    style DASH fill:#E3F2FD,stroke:#1976D2
    style AUTH_ROUTES fill:#FFF3E0,stroke:#FF9800
    style PUBLIC fill:#F3E5F5,stroke:#9C27B0
```

---

## 3.2 FE Auth Flow (Detailed)

Alur autentikasi lengkap dari halaman login hingga masuk dashboard.

```mermaid
flowchart TD
    START([User Opens App]) --> VISIT{"Current URL?"}

    VISIT -->|"/auth/*"| GUEST_CHECK{GuestGuard<br/>Is Logged In?}
    VISIT -->|"/dashboard/*"| AUTH_CHECK{AuthGuard<br/>Has Session?}
    VISIT -->|Other| PUBLIC_PAGE["Show Public Page"]

    GUEST_CHECK -->|Yes| REDIRECT_DASH["Redirect to<br/>/dashboard/chat"]
    GUEST_CHECK -->|No| AUTH_PAGE["Show Auth Page"]

    AUTH_CHECK -->|No| REDIRECT_LOGIN["Redirect to<br/>/auth/sign-in"]
    AUTH_CHECK -->|Yes| WS_CHECK{WorkspaceGuard<br/>Has Workspace?}

    WS_CHECK -->|No| REDIRECT_WS["Redirect to<br/>/dashboard/workspace/create"]
    WS_CHECK -->|Yes| ROLE_CHECK{RouteRoleGuard<br/>Has Permission?}

    ROLE_CHECK -->|No| REDIRECT_403["Redirect to<br/>/error/403"]
    ROLE_CHECK -->|Yes| SHOW_PAGE["Show Dashboard Page"]

    subgraph SIGNIN_FLOW["Sign-In Process"]
        AUTH_PAGE --> SIGNIN["BetterAuth.SignInPage"]
        SIGNIN --> INPUT["Input Email + Password"]
        INPUT --> CLICK["Click Sign In"]
        CLICK --> API_CALL["authClient.signIn.email()<br/>POST /api/v1/auth/sign-in/email-password"]
        API_CALL --> SUCCESS{Success?}
        SUCCESS -->|No| ERR_MSG["Show Error<br/>'Invalid credentials'"]
        SUCCESS -->|Yes| SESSION_SET["Session Cookie Set<br/>AuthProvider Context Updated"]
        SESSION_SET --> REDIRECT_DASH
        ERR_MSG --> INPUT
    end

    subgraph INVITE_FLOW["Invitation Flow"]
        ACCEPT_INV["/accept-invitation/:id"] --> CAPTCHA["ReCAPTCHA Verification"]
        CAPTCHA --> VERIFY{Captcha Valid?}
        VERIFY -->|No| CAPTCHA
        VERIFY -->|Yes| ACCEPT_API["authClient.organization<br/>.acceptInvitation(id)"]
        ACCEPT_API --> SUCCESS_INV{Success?}
        SUCCESS_INV -->|No| INV_ERR["Show Error"]
        SUCCESS_INV -->|Yes| SET_ACTIVE["SetActive Organization"]
        SET_ACTIVE --> REDIRECT_DASH
        INV_ERR --> CAPTCHA
    end

    style START fill:#C8E6C9,stroke:#4CAF50
    style REDIRECT_LOGIN fill:#FFCDD2,stroke:#F44336
    style REDIRECT_403 fill:#FFCDD2,stroke:#F44336
    style SHOW_PAGE fill:#BBDEFB,stroke:#2196F3
    style SIGNIN fill:#FFF8E1,stroke:#F9A825
```

---

## 3.3 FE Chat Module Flow (Detailed)

Modul Chat adalah modul terbesar (82 files). Diagram ini menunjukkan alur lengkap.

> **Catatan Penting (Kondisi Aktual):**
> - **Conversations**: Di-fetch **Full GET**. BE route menerima parameter `page`/`limit` dan memanggil `calculatePagination()`, namun repository **tidak menggunakan** `.limit()`/`.offset()` di query DB. Semua conversations di-return sekaligus.
> - **Messages**: Di-fetch **Full GET**. Parameter `page`/`limit` di route, service, dan repository BE **sudah di-comment out**. Response mengembalikan `page:0, limit:0, totalPages:0` (dummy). Semua messages dalam conversation chain di-return sekaligus.
> - **Infinite Scroll**: Hook `use-message-list-infinite-scroll.ts` dan `use-message-list-scroll-persistence.ts` masih di-import di `chat-message-list.tsx`, tapi **tidak pernah ter-trigger** karena `hasMore` selalu `false` (karena response pagination dummy). Hook `use-infinite-scroll.ts` dan `use-messages-scroll.ts` adalah **dead code** (tidak di-import di mana pun).
> - **Auto-Scroll**: Hook `use-message-list-initial-load.ts` tetap aktif untuk auto-scroll to bottom saat initial load.

```mermaid
flowchart TD
    CHAT_PAGE["Chat Page<br/>/dashboard/chat"] --> INIT["Initialize ChatContext"]
    INIT --> LOAD_CHANNELS["Load Channels<br/>GET /channels/with-unread-count"]
    INIT --> LOAD_COUNTS["Load Chat Counts<br/>GET /conversations/total-counts-chat"]
    INIT --> CONNECT_RT["Connect Real-time<br/>Pusher + Socket.IO"]

    LOAD_CHANNELS --> RENDER_LAYOUT["Render ChatLayout<br/>(3-Column Layout)"]
    LOAD_COUNTS --> RENDER_LAYOUT
    CONNECT_RT --> RENDER_LAYOUT

    subgraph LEFT_PANEL["LEFT PANEL — ChatNav"]
        RENDER_LAYOUT --> CH_NAV["chat-nav.tsx"]
        CH_NAV --> CH_FOOTER["chat-channel-list-footer.tsx<br/>Channel filter tabs"]
        CH_FOOTER --> CH_SEARCH["chat-nav-search-results.tsx<br/>Search conversations"]
        CH_SEARCH --> CH_ITEM["chat-nav-item.tsx<br/>Conversation list item"]
        CH_ITEM --> CH_LIST["Conversation List (Full GET)<br/>use-conversation-pagination.ts<br/>⚠️ BE route terima page/limit<br/>tapi repository tidak pakai"]
    end

    subgraph FILTERS["Conversation Filters"]
        FILTER_GROUP["Filter Options:"] --> F1["Channel Filter<br/>(WhatsApp, Instagram, etc.)"]
        FILTER_GROUP --> F2["Status Filter<br/>All / My / Unassigned / Assigned / Resolved"]
        FILTER_GROUP --> F3["Tag Filter"]
        FILTER_GROUP --> F4["Date Range Filter"]
        FILTER_GROUP --> F5["24h Window Filter<br/>(WhatsApp only)"]
        FILTER_GROUP --> F6["First Response Filter"]
    end

    CH_LIST --> FILTERS

    subgraph CENTER_PANEL["CENTER PANEL — ChatRoom"]
        CH_LIST -->|"Select Conversation"| LOAD_MSG["Load All Messages (Full GET)<br/>GET /conversation-messages<br/>use-message-list-initial-load.ts<br/>⚠️ BE limit/offset di-comment out<br/>→ returns all messages"]

        LOAD_MSG --> MSG_LIST["chat-message-list.tsx<br/>Message list<br/>(auto-scroll to bottom on load)"]
        MSG_LIST --> MSG_ITEM["chat-message-item.tsx<br/>Individual message bubble"]
        MSG_ITEM --> MSG_TYPES["Message Types:<br/>TEXT, IMAGE, VIDEO, AUDIO,<br/>DOCUMENT, TEMPLATE, SYSTEM,<br/>INTERNAL_NOTE"]
        MSG_TYPES --> DATE_SEP["chat-date-separator.tsx<br/>Date separators between messages"]
    end

    subgraph INPUT_AREA["MESSAGE INPUT"]
        MSG_LIST --> MSG_INPUT["chat-message-input.tsx"]
        MSG_INPUT --> TEXT_INPUT["bubble-editor.tsx<br/>(TipTap Rich Editor)"]
        MSG_INPUT --> FILE_BTN["File Upload<br/>use-file-upload.ts"]
        MSG_INPUT --> EMOJI_BTN["Emoji Picker<br/>use-emoji-picker.ts"]
        MSG_INPUT --> QUICK_BTN["Quick Message<br/>quick-message-overlay.tsx<br/>use-quick-message.ts"]
        MSG_INPUT --> TEMPL_BTN["WhatsApp Template<br/>chat-template-dialog.tsx<br/>use-template-dialog.ts"]
        MSG_INPUT --> REPLY_BTN["Reply to Message"]
        MSG_INPUT --> SEND_BTN["Send Button"]
    end

    subgraph SEND_FLOW["SEND MESSAGE FLOW"]
        TEXT_INPUT --> SEND_BTN
        FILE_BTN --> UPLOAD["use-file-upload.ts<br/>POST /upload-media"]
        UPLOAD --> SEND_BTN
        QUICK_BTN --> INSERT_QM["Insert Quick Message Text"]
        TEMPL_BTN --> SEND_TEMPL["POST /conversation-messages/template"]
        SEND_BTN -->|"POST /conversation-messages<br/>(JSON or Multipart)"| API_SEND
        INSERT_QM --> TEXT_INPUT
    end

    subgraph RT_UPDATE["REAL-TIME UPDATE"]
        API_SEND -->|"Message Sent"| PUSHER_RECV["use-pusher-chat.ts<br/>Listen: new-message"]
        PUSHER_RECV --> SWR_MUTATE["SWR mutate()<br/>Revalidate messages cache"]
        SWR_MUTATE --> UI_UPDATE["Update Message List<br/>(Optimistic UI)"]
    end

    subgraph RIGHT_PANEL["RIGHT PANEL — Details Sidebar"]
        RENDER_LAYOUT --> INFO_TAB["Information Tab<br/>chat-room-information.tsx<br/>Contact details, tags, channels"]
        RENDER_LAYOUT --> NOTE_TAB["Notes Tab<br/>note-list, note-item,<br/>note-detail, note-form<br/>CRUD: POST /notes"]
        RENDER_LAYOUT --> TICKET_TAB["Ticket Tab<br/>ticket-list, ticket-item,<br/>ticket-detail, ticket-form<br/>Linked tickets to conversation"]
    end

    subgraph HEADER_ACTIONS["HEADER ACTIONS"]
        RENDER_LAYOUT --> CH_HEADER["chat-header-details.tsx"]
        CH_HEADER --> ASSIGN["Assign Conversation<br/>chat-assign-dialog.tsx<br/>PATCH /conversations/:id/status"]
        CH_HEADER --> RESOLVE["Resolve Conversation<br/>chat-resolve-dialog.tsx<br/>PATCH /conversations/:id/status"]
        CH_HEADER --> HISTORY["View History<br/>chat-room-history.tsx<br/>GET /conversations/:id/history"]
        CH_HEADER --> GET_NEW["Get New Chat<br/>POST /conversations/get-new-chat<br/>(Claim next unassigned)"]
        CH_HEADER --> SEARCH_MSG["Search Messages<br/>chat-search-dialog.tsx<br/>GET /conversation-messages/search"]
        CH_HEADER --> BULK_RESOLVE["Bulk Resolve<br/>bulk-resolve-modal.tsx<br/>POST /conversations/bulk-resolve"]
    end

    style CHAT_PAGE fill:#E3F2FD,stroke:#1976D2
    style LEFT_PANEL fill:#E8F5E9,stroke:#4CAF50
    style CENTER_PANEL fill:#FFF3E0,stroke:#FF9800
    style RIGHT_PANEL fill:#F3E5F5,stroke:#9C27B0
    style SEND_FLOW fill:#FFEBEE,stroke:#F44336
    style RT_UPDATE fill:#E0F7FA,stroke:#00BCD4
```

---

## 3.4 FE Campaign Module Flow (Detailed)

Alur lengkap modul Campaign dari pembuatan template hingga eksekusi.

```mermaid
flowchart TD
    CAMP_PAGE["Campaign Page<br/>/dashboard/campaign"] --> CAMP_LAYOUT["campaign-layout.tsx<br/>(Tab Navigation)"]

    CAMP_LAYOUT --> TAB_CAMPAIGNS["Tab: Campaigns"]
    CAMP_LAYOUT --> TAB_TEMPLATES["Tab: Templates"]
    CAMP_LAYOUT --> TAB_RECIPIENTS["Tab: Recipient Lists"]

    subgraph CAMPAIGNS_TAB["CAMPAIGNS MANAGEMENT"]
        TAB_CAMPAIGNS --> CAMP_LIST["campaign-view.tsx<br/>Campaign List DataTable"]
        CAMP_LIST --> CAMP_TOOLBAR["campaign-table-toolbar.tsx<br/>Filters + Search"]
        CAMP_LIST --> CAMP_ROW["campaign-table-row.tsx<br/>Campaign Row"]
        CAMP_ROW --> CAMP_ACTIONS["Campaign Actions"]
        CAMP_ACTIONS --> VIEW_DETAIL["View Detail<br/>/dashboard/campaign/:id<br/>campaign-detail-view.tsx"]
        CAMP_ACTIONS --> EDIT["Edit Campaign<br/>/dashboard/campaign/:id/edit<br/>campaign-create-view.tsx"]
        CAMP_ACTIONS --> EXECUTE["Execute Campaign<br/>POST /campaigns/:id/execute"]
        CAMP_ACTIONS --> DELETE["Delete Campaign<br/>DELETE /campaigns/:id"]

        CAMP_LIST --> CREATE_BTN["+ New Campaign"]
        CREATE_BTN --> CREATE_FORM["campaign-create-view.tsx<br/>campaign-create-form.tsx"]
        CREATE_FORM --> FORM_STEP1["Step 1: Campaign Name<br/>& Description"]
        FORM_STEP1 --> FORM_STEP2["Step 2: Select Channel<br/>(WhatsApp channel only)"]
        FORM_STEP2 --> FORM_STEP3["Step 3: Select Template<br/>(from approved templates)"]
        FORM_STEP3 --> FORM_STEP4["Step 4: Select Recipient List<br/>(from recipient lists)"]
        FORM_STEP4 --> SAVE_DRAFT["Save as DRAFT<br/>POST /campaigns"]
    end

    subgraph TEMPLATES_TAB["TEMPLATE MANAGEMENT"]
        TAB_TEMPLATES --> TEMPL_LIST["campaign-templates-view.tsx<br/>Template List"]
        TEMPL_LIST --> TEMPL_TOOLBAR["template-table-toolbar.tsx"]
        TEMPL_LIST --> TEMPL_ROW["template-table-row.tsx"]
        TEMPL_ROW --> TEMPL_ACTIONS["Template Actions"]
        TEMPL_ACTIONS --> VIEW_TEMPL["View Detail<br/>campaign-templates-detail.tsx"]
        TEMPL_ACTIONS --> EDIT_TEMPL["Edit Template<br/>campaign-template-edit.tsx"]
        TEMPL_ACTIONS --> SYNC_TEMPL["Sync to WhatsApp<br/>POST /templates/:id/sync"]
        TEMPL_ACTIONS --> DEL_TEMPL["Delete Template<br/>DELETE /templates/:id"]

        TEMPL_LIST --> CREATE_TEMPL["+ New Template"]
        CREATE_TEMPL --> TEMPL_CREATE["campaign-template-create.tsx"]
        TEMPL_CREATE --> TEMPL_FORM["template-form-fields.tsx<br/>template-form-schema.ts"]
        TEMPL_FORM --> TEMPL_HEADER["Header Component<br/>(Text / Image / Video)"]
        TEMPL_FORM --> TEMPL_BODY["Body Component<br/>(Text + Variables {{1}}, {{2}}...)"]
        TEMPL_FORM --> TEMPL_FOOTER["Footer Component<br/>(Text)"]
        TEMPL_FORM --> TEMPL_BUTTONS["Buttons Component<br/>(Quick Reply / URL / Phone)"]
        TEMPL_BODY --> UPLOAD_MEDIA["Upload Header Media<br/>POST /templates/upload-media<br/>(Meta Resumable API)"]
        TEMPL_FORM --> SAVE_TEMPL["Create Template<br/>POST /templates"]
        SAVE_TEMPL --> SYNC_WA["Sync to WhatsApp<br/>POST /templates/:id/sync"]
    end

    subgraph RECIPIENTS_TAB["RECIPIENT LIST MANAGEMENT"]
        TAB_RECIPIENTS --> RL_LIST["campaign-recipient-lists-view.tsx"]
        RL_LIST --> RL_TOOLBAR["recipient-list-table-toolbar.tsx"]
        RL_LIST --> RL_ROW["recipient-list-table-row.tsx"]
        RL_ROW --> RL_ACTIONS["List Actions"]
        RL_ACTIONS --> VIEW_RL["View List Detail<br/>campaign-recipient-list-detail.tsx"]
        RL_ACTIONS --> EDIT_RL["Edit List"]
        RL_ACTIONS --> DEL_RL["Delete List<br/>DELETE /campaign-recipient-lists/:id"]

        RL_LIST --> CREATE_RL["+ New Recipient List"]
        CREATE_RL --> WIZARD["recipient-list-create-wizard.tsx<br/>(Step-by-step Wizard)"]
        WIZARD --> W_STEP1["Step 1: Name & Description<br/>+ Variable Definitions<br/>(e.g. {{nama}}, {{no_pesanan}})"]
        W_STEP1 --> W_STEP2["Step 2: Select Contacts<br/>recipient-list-select-contacts-dialog.tsx<br/>(From contact database)"]
        W_STEP2 --> W_STEP3["Step 3: Input Variable Values<br/>recipient-list-input-variables-dialog.tsx<br/>(Per contact: nama=John, no_pesanan=123)"]
        W_STEP3 --> SAVE_RL["Save Recipient List<br/>POST /campaign-recipient-lists"]

        VIEW_RL --> ITEMS_LIST["List Items<br/>campaign-recipient-list-item-table-row.tsx"]
        ITEMS_LIST --> ADD_CONTACTS["Add More Contacts<br/>recipient-list-add-contacts-dialog.tsx<br/>POST /campaign-recipient-lists/:id/contacts"]
        ITEMS_LIST --> RM_CONTACTS["Remove Contacts<br/>DELETE /campaign-recipient-lists/:id/contacts"]
    end

    subgraph EXECUTION_FLOW["CAMPAIGN EXECUTION"]
        EXECUTE --> EXEC_API["POST /campaigns/:id/execute"]
        EXEC_API --> BE_PROCESS["Backend Processing<br/>(See BE Campaign Flow)"]
        BE_PROCESS --> DELIVERY_WEBHOOK["WhatsApp Delivery Webhooks<br/>→ Update per-recipient status"]
        DELIVERY_WEBHOOK --> VIEW_STATS["View Campaign Stats<br/>sent / delivered / read / failed"]
    end

    style CAMPAIGNS_TAB fill:#E8F5E9,stroke:#4CAF50
    style TEMPLATES_TAB fill:#FFF3E0,stroke:#FF9800
    style RECIPIENTS_TAB fill:#F3E5F5,stroke:#9C27B0
    style EXECUTION_FLOW fill:#FFEBEE,stroke:#F44336
```

---

## 3.5 FE Ticket Module Flow (Detailed)

Alur lengkap modul Ticket dari pembuatan hingga lifecycle management.

```mermaid
flowchart TD
    TICKET_PAGE["Ticket Page<br/>/dashboard/ticket"] --> TICKET_LIST["ticket-list-view.tsx<br/>Ticket DataTable"]

    TICKET_LIST --> TOOLBAR["ticket-table-toolbar.tsx<br/>Status Filter | Assignee Filter<br/>Contact Search"]
    TICKET_LIST --> TABLE["Ticket Table Columns:<br/>Number, Title, Status,<br/>Assignee, Created, Updated"]

    TABLE --> CREATE_BTN["+ New Ticket"]
    TABLE --> SELECT_ROW["Select Ticket → Detail View"]
    TABLE --> BATCH_ACTIONS["Batch Actions<br/>(Checkbox Selection)"]

    subgraph CREATE_FLOW["CREATE TICKET"]
        CREATE_BTN --> CREATE_VIEW["ticket-create-view.tsx<br/>(Standalone)"]
        CREATE_VIEW --> CREATE_FORM["ticket-create-form.tsx"]
        CREATE_FORM --> FORM_TITLE["Ticket Title *"]
        CREATE_FORM --> FORM_DESC["Description *"]
        CREATE_FORM --> FORM_CONV["Link Conversation<br/>(optional - select from list)"]
        CREATE_FORM --> FORM_CONTACT["Link Contact<br/>(optional - select from list)"]
        CREATE_FORM --> FORM_ATTACH["Attachments<br/>POST /tickets/upload-media"]
        CREATE_FORM --> FORM_TEMPL["Use Template<br/>/dashboard/ticket/templates"]
        FORM_ATTACH --> SUBMIT["POST /tickets<br/>→ Status: TODO"]
        FORM_TITLE --> SUBMIT
        FORM_DESC --> SUBMIT
    end

    subgraph DETAIL_FLOW["TICKET DETAIL VIEW"]
        SELECT_ROW --> DETAIL["ticket-detail-view.tsx<br/>/dashboard/ticket/:id"]
        DETAIL --> INFO["Ticket Info<br/>Number, Title, Description,<br/>Status, Assignee, Dates"]
        DETAIL --> ATTACHMENTS["ticket-attachment-preview.tsx<br/>File attachments"]
        DETAIL --> HISTORY["ticket-history-timeline.tsx<br/>Status change history"]
        DETAIL --> ACTION_BUTTONS["Status Action Buttons"]
    end

    subgraph ACTIONS["TICKET LIFECYCLE ACTIONS"]
        ACTION_BUTTONS --> ASSIGN["Assign to Agent<br/>ticket-assign-dialog.tsx<br/>PUT /tickets/:id<br/>assignedTo, assignedBy"]
        ACTION_BUTTONS --> START["Start Progress<br/>PUT /tickets/:id<br/>status: IN_PROGRESS"]
        ACTION_BUTTONS --> RESOLVE["Resolve<br/>ticket-resolve-dialog.tsx<br/>PUT /tickets/:id<br/>status: RESOLVED + resolvedNote"]
        ACTION_BUTTONS --> DONE["Mark Done<br/>ticket-done-dialog.tsx<br/>PUT /tickets/:id<br/>status: DONE"]
        ACTION_BUTTONS --> REJECT["Reject<br/>ticket-reject-dialog.tsx<br/>PUT /tickets/:id<br/>status: REJECTED + rejectReason"]
        ACTION_BUTTONS --> EDIT["Edit Ticket<br/>ticket-edit-view.tsx<br/>PUT /tickets/:id"]
    end

    subgraph BATCH_OP["BATCH OPERATIONS"]
        BATCH_ACTIONS --> BATCH_ASSIGN["Batch Assign<br/>ticket-batch-assign-dialog.tsx<br/>Loop PUT /tickets/:id"]
        BATCH_ACTIONS --> BATCH_STATUS["Batch Update Status<br/>→ IN_PROGRESS<br/>Loop PUT /tickets/:id"]
    end

    subgraph TICKET_TEMPLATES["TICKET TEMPLATES"]
        TICKET_PAGE --> TEMPL_NAV["/dashboard/ticket/templates"]
        TEMPL_NAV --> TEMPL_LIST_T["ticket-template-list-view.tsx"]
        TEMPL_LIST_T --> TEMPL_CREATE_T["+ New Ticket Template<br/>ticket-template-create-view.tsx"]
        TEMPL_CREATE_T --> TEMPL_FORM_T["ticket-template-form-fields.tsx"]
        TEMPL_FORM_T --> TEMPL_TYPE["Template Type:<br/>TICKET_START / TICKET_END"]
        TEMPL_FORM_T --> SAVE_TEMPL_T["POST /templates/ticket"]
    end

    subgraph EMBEDDED["TICKET FROM CHAT"]
        CHAT_PANEL["Chat Room<br/>Right Panel → Ticket Tab"] --> TICKET_TAB["chat-room-ticket.tsx"]
        TICKET_TAB --> TICKET_FORM_CHAT["ticket-form.tsx<br/>(Inline Create)"]
        TICKET_FORM_CHAT --> CREATE_FROM_CHAT["Create Ticket<br/>(auto-links current conversation)"]
        TICKET_TAB --> TICKET_LIST_CHAT["ticket-list.tsx<br/>(Linked tickets list)"]
    end

    style CREATE_FLOW fill:#E8F5E9,stroke:#4CAF50
    style DETAIL_FLOW fill:#FFF3E0,stroke:#FF9800
    style ACTIONS fill:#FFEBEE,stroke:#F44336
    style TICKET_TEMPLATES fill:#E3F2FD,stroke:#1976D2
    style EMBEDDED fill:#F3E5F5,stroke:#9C27B0
```

---

## 3.6 FE Settings Module Flow (Detailed)

Alur lengkap halaman Settings beserta role guard pada setiap sub-menu.

```mermaid
flowchart TD
    SETTINGS_ENTRY["/dashboard/settings"] --> REDIRECT["Redirect to<br/>/dashboard/settings/user/list"]

    SETTINGS_ENTRY --> SETTINGS_NAV{{"Settings Navigation"}}

    subgraph USER_MGMT["USER MANAGEMENT [admin, owner]"]
        SETTINGS_NAV --> SET_USER["/settings/user/list<br/>SettingsUserListPage"]
        SETTINGS_NAV --> SET_USER_NEW["/settings/user/new<br/>UserCreatePage"]
        SETTINGS_NAV --> SET_USER_EDIT["/settings/user/:id/edit<br/>UserEditPage"]
        SETTINGS_NAV --> SET_ROLE_PERM["/settings/user/role-permission<br/>SettingsUserRolePermissionPage"]

        SET_USER --> USER_TABLE["User List Table<br/>GET /auth/admin/list-users"]
        USER_TABLE --> USER_ACTIONS["User Actions"]
        USER_ACTIONS --> CREATE_USER["Create User<br/>POST /auth/admin/create-user"]
        USER_ACTIONS --> EDIT_USER["Edit User<br/>POST /auth/admin/update-user"]
        USER_ACTIONS --> SET_ROLE["Set Role<br/>POST /auth/admin/set-role"]
        USER_ACTIONS --> BAN_USER["Ban User"]
        USER_ACTIONS --> UNBAN["Unban User<br/>POST /auth/admin/unban-user"]
        USER_ACTIONS --> INVITE["Invite Member<br/>POST /auth/organization/invite-member"]
    end

    subgraph CHANNEL_MGMT["CHANNEL MANAGEMENT [admin, owner]"]
        SETTINGS_NAV --> SET_CH["/settings/channel<br/>ChannelPage"]
        SETTINGS_NAV --> SET_CH_NEW["/settings/channel/new<br/>ChannelCreatePage"]
        SETTINGS_NAV --> SET_CH_EDIT["/settings/channel/:id/edit<br/>ChannelEditPage"]

        SET_CH --> CH_LIST["Channel List<br/>GET /channels"]
        CH_LIST --> CH_ACTIONS["Channel Actions"]
        CH_ACTIONS --> CONNECT_WA["Connect WhatsApp<br/>POST /channels/whatsapp<br/>(Embedded Signup Flow)"]
        CH_ACTIONS --> CONNECT_IG["Connect Instagram<br/>POST /channels/instagram<br/>(Business Login Flow)"]
        CH_ACTIONS --> EDIT_CH["Edit Channel<br/>PUT /channels/:id"]
        CH_ACTIONS --> GEN_WEBHOOK["Generate Webhook Token<br/>POST /channels/:id/generate-webhook"]
        CH_ACTIONS --> DEL_CH["Delete Channel<br/>DELETE /channels/:id"]
    end

    subgraph WS_MGMT["WORKSPACE MANAGEMENT [owner only]"]
        SETTINGS_NAV --> SET_WS["/settings/workspace<br/>WorkspacePage"]
        SETTINGS_NAV --> SET_WS_NEW["/settings/workspace/new<br/>WorkspaceCreatePage"]
        SETTINGS_NAV --> SET_WS_EDIT["/settings/workspace/:id/edit<br/>WorkspaceEditPage"]

        SET_WS --> WS_LIST["Workspace List<br/>authClient.organization.list()"]
        WS_LIST --> WS_ACTIONS["Workspace Actions"]
        WS_ACTIONS --> CREATE_WS["Create Workspace<br/>authClient.organization.create()"]
        WS_ACTIONS --> EDIT_WS["Edit Workspace<br/>authClient.organization.update()"]
        WS_ACTIONS --> DEL_WS["Delete Workspace<br/>authClient.organization.delete()"]
        WS_ACTIONS --> SESSION_CFG["Session Time Config<br/>PUT /workspaces/:id/session-time<br/>Options: 5min, 30min, 1hour, 24hour, never"]
    end

    subgraph ACCOUNT["MY ACCOUNT [all roles]"]
        SETTINGS_NAV --> SET_ACCOUNT["/settings/account<br/>AccountGeneralPage"]
        SETTINGS_NAV --> SET_PWD["/settings/account/change-password<br/>AccountChangePasswordPage"]

        SET_ACCOUNT --> PROFILE["Profile Settings<br/>PUT /user/update-user<br/>(username, fullname, phone,<br/>photo, image_url, status)"]
        SET_PWD --> CHANGE_PWD["Change Password<br/>POST /auth/change-password<br/>(currentPassword, newPassword,<br/>revokeOtherSessions)"]
    end

    subgraph OTHER_SETTINGS["OTHER SETTINGS [admin, owner]"]
        SETTINGS_NAV --> SET_TAG["/settings/tag<br/>Tag Management<br/>CRUD /tags"]
        SETTINGS_NAV --> SET_OH["/settings/office-hours<br/>Office Hours & Auto Response<br/>CRUD /office-hour-*"]
        SETTINGS_NAV --> SET_QM["/settings/quick-message<br/>Quick Reply Templates<br/>CRUD /message-templates"]
        SETTINGS_NAV --> SET_API["/settings/api-keys<br/>API Key Management<br/>CRUD /workspace-api-keys"]
        SETTINGS_NAV --> SET_RC["/settings/resolve-category<br/>Resolve Categories<br/>CRUD /conversation-resolve-category"]
    end

    subgraph OFFICE_HOURS_DETAIL["OFFICE HOURS DETAIL"]
        SET_OH --> OH_SCHEDULE["Schedule Configuration<br/>Per Channel"]
        OH_SCHEDULE --> OH_DAYS["Days: Mon-Sun<br/>Start Time, End Time<br/>Timezone"]
        OH_SCHEDULE --> OH_STATUS["useOfficeHoursStatus hook<br/>Auto-check every minute<br/>→ Online / Offline"]

        SET_OH --> OH_RESPONSE["Auto Response Configuration<br/>Per Channel"]
        OH_RESPONSE --> OH_DURING["During Office Hours<br/>Auto-response message"]
        OH_RESPONSE --> OH_OUTSIDE["Outside Office Hours<br/>Auto-response message"]
    end

    style USER_MGMT fill:#E8F5E9,stroke:#4CAF50
    style CHANNEL_MGMT fill:#FFF3E0,stroke:#FF9800
    style WS_MGMT fill:#FFEBEE,stroke:#F44336
    style ACCOUNT fill:#E3F2FD,stroke:#1976D2
    style OTHER_SETTINGS fill:#F3E5F5,stroke:#9C27B0
```

---

## 3.7 FE Data Fetching Architecture (SWR Pattern)

Diagram yang menunjukkan pola data fetching menggunakan SWR di seluruh aplikasi.

```mermaid
flowchart TD
    COMPONENT["React Component<br/>(Page / Section)"] --> HOOK["Custom Hook<br/>(use-conversations,<br/>use-messages, etc.)"]
    HOOK --> SWR_HOOK["useSWR()<br/>SWR Hook"]
    SWR_HOOK --> FETCHER["Axios Fetcher<br/>/src/lib/fetcher.ts"]
    FETCHER --> API["API Request<br/>GET /api/v1/u/*"]

    API --> RESPONSE{"Response?"}
    RESPONSE -->|200 OK| CACHE["SWR Cache<br/>(Key: URL + Params)"]
    RESPONSE -->|Error| ERROR_HANDLER["Error Handling"]
    ERROR_HANDLER --> SHOW_TOAST["Snackbar Toast<br/>Error Message"]

    CACHE --> RENDER["Render Component<br/>with Cached Data"]
    RENDER --> IDLE{"Data Stale?"}

    IDLE -->|Yes| REVALIDATE["Auto Revalidation<br/>(revalidateOnFocus,<br/>revalidateOnReconnect)"]
    IDLE -->|No| WAIT["Wait for Event"]

    REVALIDATE --> FETCHER

    subgraph RT_EVENTS["Real-Time Triggered Revalidation"]
        PUSHER_EV["Pusher Event Received"] --> MUTATE["SWR mutate()<br/>Invalidate specific key"]
        SOCKET_EV["Socket.IO Event"] --> MUTATE
        MUTATE --> FETCHER
    end

    subgraph MANUAL["Manual Mutations"]
        OPTIMISTIC["Optimistic Update"] --> LOCAL_UPDATE["Update local cache first"]
        MANUAL_CALL["Manual API Call<br/>(POST/PUT/DELETE)"] --> MANUAL_MUTATE["mutate() after success"]
        MANUAL_CALL -->|"Error"| ROLLBACK["Rollback optimistic update"]
        LOCAL_UPDATE --> MANUAL_MUTATE
    end
```
