diff --git a/apps/docs-dev/package.json b/apps/docs-dev/package.json index 463a9b6..a825bb8 100644 --- a/apps/docs-dev/package.json +++ b/apps/docs-dev/package.json @@ -12,6 +12,7 @@ "dependencies": { "@repo/ui": "workspace:*", "dayjs": "^1.11.19", + "lucide-vue-next": "^1.0.0", "react": "^19.2.3", "react-dom": "^19.2.3" }, @@ -20,6 +21,7 @@ "@repo/typescript-config": "workspace:*", "eslint": "^8.57.0", "mermaid": "^11.15.0", + "plantuml-encoder": "^1.4.0", "typescript": "5.5.4", "vitepress": "^1.6.4", "vitepress-plugin-mermaid": "^2.0.17", diff --git a/apps/docs-dev/src/.vitepress/config.mts b/apps/docs-dev/src/.vitepress/config.mts index 7ce6495..db1212c 100644 --- a/apps/docs-dev/src/.vitepress/config.mts +++ b/apps/docs-dev/src/.vitepress/config.mts @@ -1,14 +1,17 @@ import { defineConfig } from 'vitepress'; import { withMermaid } from 'vitepress-plugin-mermaid'; +import { plantumlPlugin } from './plantuml'; const config = withMermaid( defineConfig({ - // title: "Frontend Monorepo", - title: 'Frontend Arch', - description: 'Centralized documentation for the Enterprise Frontend Monorepo', - head: [ - ['link', { rel: 'icon', href: '/favicon.svg' }], // Jika Anda menggunakan favicon.svg - ], + title: 'TrackGo', + description: 'User guides for TrackGo web and mobile', + head: [['link', { rel: 'icon', href: '/favicon.svg' }]], + markdown: { + config(md) { + plantumlPlugin(md); + }, + }, themeConfig: { search: { provider: 'local', @@ -17,58 +20,57 @@ const config = withMermaid( }, }, logo: '/logo.svg', - nav: [{ text: 'Docs', link: '/overview' }], + nav: [ + { text: 'User guides', link: '/user/' }, + { text: 'Web', link: '/user/web/' }, + { text: 'Mobile', link: '/user/mobile/' }, + ], sidebar: [ { - text: 'Getting Started', + text: 'User guides', + items: [{ text: 'What is TrackGo', link: '/user/' }], + }, + { + text: 'Web', + collapsed: false, + items: [ + { text: 'Overview', link: '/user/web/' }, + { text: 'Set up your company', link: '/user/web/setup' }, + { text: 'Plans and visits', link: '/user/web/plans' }, + { text: 'Sales workflow', link: '/user/web/sales-workflow' }, + { text: 'Logistics', link: '/user/web/logistics' }, + { text: 'Timeline', link: '/user/web/timeline' }, + { text: 'Import CSV', link: '/user/web/import' }, + ], + }, + { + text: 'Mobile', + collapsed: false, + items: [ + { text: 'Overview', link: '/user/mobile/' }, + { text: 'Check in', link: '/user/mobile/check-in' }, + { text: 'Daily work', link: '/user/mobile/daily-work' }, + ], + }, + { + text: 'Developer reference', + collapsed: true, items: [ { text: 'Project Overview', link: '/overview' }, { text: 'Development Setup', link: '/setup' }, - ], - }, - { - text: 'Core Architecture', - collapsed: false, - items: [ - // { text: 'API & Domain Logic', link: '/packages/core-api/' }, - { - text: 'API & Domain Logic', - collapsed: false, - items: [ - { text: 'API Engine', link: '/packages/core-api' }, - { text: 'Data Transformers', link: '/packages/core-api/transformers' }, - ], - }, - + { text: 'API Engine', link: '/packages/core-api' }, + { text: 'Data Transformers', link: '/packages/core-api/transformers' }, { text: 'Event Bus System', link: '/packages/core-events/' }, { text: 'Storage & Persistence', link: '/packages/core-storage/' }, { text: 'I18n & Localization', link: '/packages/core-i18n/' }, - ], - }, - { - text: 'UI System', - collapsed: false, - items: [ - { text: 'Overview', link: '/packages/ui/' }, + { text: 'UI Overview', link: '/packages/ui/' }, { text: 'App Layout', link: '/packages/ui/CORE-APP-SHELL' }, { text: 'Action Tools', link: '/packages/ui/ACTION-TOOLS' }, { text: 'Form Primitives', link: '/packages/ui/FORM-COMPONENTS' }, - ], - }, - { - text: 'TrackGo Web', - collapsed: false, - items: [ - { text: 'Overview', link: '/apps/web/' }, - { text: 'Sales Workflow', link: '/apps/web/SALES_WORKFLOW' }, - ], - }, - { - text: 'Desktop Ecosystem', - collapsed: false, - items: [ - { text: 'Overview', link: '/apps/desktop/' }, + { text: 'Web Overview', link: '/apps/web/' }, + { text: 'Sales Workflow (legacy)', link: '/apps/web/SALES_WORKFLOW' }, + { text: 'Desktop Overview', link: '/apps/desktop/' }, { text: 'Lifecycle & Configuration', link: '/apps/desktop/CONFIGURATION' }, { text: 'IPC & Bridge Architecture', link: '/apps/desktop/IPC_ARCHITECTURE' }, { text: 'Distribution & Auto-Update', link: '/apps/desktop/AUTO_UPDATER' }, @@ -87,25 +89,21 @@ const config = withMermaid( ], }, - // Mermaid configuration mermaid: { theme: 'default', }, - // Fix cascading CJS/ESM SyntaxErrors caused by Vite dynamically discovering mermaid vite: { + ssr: { + noExternal: ['lucide-vue-next'], + }, optimizeDeps: { - include: ['mermaid'], + include: ['mermaid', 'lucide-vue-next'], }, }, }), ); -// Pnpm strict workspace workaround: -// vitepress-plugin-mermaid aggressively injects sub-dependencies into optimizeDeps.include. -// Because pnpm uses strict symlinks, Vite fails to resolve these sub-dependencies from the project root, -// causing pre-bundling to fail and cascading CJS/ESM SyntaxErrors in the browser. -// We strip them out so esbuild can naturally inline them into the 'mermaid' chunk instead. if (config.vite?.optimizeDeps?.include) { config.vite.optimizeDeps.include = config.vite.optimizeDeps.include.filter( (dep) => !['@braintree/sanitize-url', 'debug', 'cytoscape-cose-bilkent', 'cytoscape'].includes(dep), diff --git a/apps/docs-dev/src/.vitepress/plantuml-encoder.d.ts b/apps/docs-dev/src/.vitepress/plantuml-encoder.d.ts new file mode 100644 index 0000000..9bb4155 --- /dev/null +++ b/apps/docs-dev/src/.vitepress/plantuml-encoder.d.ts @@ -0,0 +1,4 @@ +declare module 'plantuml-encoder' { + export function encode(source: string): string; + export function decode(encoded: string): string; +} diff --git a/apps/docs-dev/src/.vitepress/plantuml.ts b/apps/docs-dev/src/.vitepress/plantuml.ts new file mode 100644 index 0000000..df66bdb --- /dev/null +++ b/apps/docs-dev/src/.vitepress/plantuml.ts @@ -0,0 +1,25 @@ +import { createRequire } from 'node:module'; +import type MarkdownIt from 'markdown-it'; + +const require = createRequire(import.meta.url); +const plantumlEncoder = require('plantuml-encoder') as { + encode: (source: string) => string; +}; + +export function plantumlPlugin(md: MarkdownIt): void { + const defaultFence = md.renderer.rules.fence; + if (!defaultFence) { + return; + } + + md.renderer.rules.fence = (tokens, idx, options, env, slf) => { + const token = tokens[idx]; + const info = token.info.trim().split(/\s+/)[0]; + if (info === 'plantuml') { + const encoded = plantumlEncoder.encode(token.content); + const src = `https://www.plantuml.com/plantuml/svg/${encoded}`; + return `
diagram
\n`; + } + return defaultFence(tokens, idx, options, env, slf); + }; +} diff --git a/apps/docs-dev/src/.vitepress/theme/custom.css b/apps/docs-dev/src/.vitepress/theme/custom.css index 7c09ed2..6f8aa5e 100644 --- a/apps/docs-dev/src/.vitepress/theme/custom.css +++ b/apps/docs-dev/src/.vitepress/theme/custom.css @@ -113,4 +113,35 @@ .VPNavBar .VPNavBarSearch { flex-grow: 0; } +} + +.doc-lead { + display: flex; + align-items: center; + gap: 0.5rem; + color: var(--vp-c-text-2); + margin-top: -0.25rem; +} + +.doc-icon { + display: inline-block; + vertical-align: -0.2em; + color: var(--vp-c-brand-1); + flex-shrink: 0; +} + +.plantuml-diagram { + background: #ffffff; + border: 1px solid var(--vp-c-divider); + border-radius: 8px; + padding: 12px; + margin: 16px 0; + overflow-x: auto; +} + +.plantuml-diagram img { + max-width: 100%; + height: auto; + display: block; + margin: 0 auto; } \ No newline at end of file diff --git a/apps/docs-dev/src/apps/web/SALES_WORKFLOW.md b/apps/docs-dev/src/apps/web/SALES_WORKFLOW.md index e499eed..e8727d0 100644 --- a/apps/docs-dev/src/apps/web/SALES_WORKFLOW.md +++ b/apps/docs-dev/src/apps/web/SALES_WORKFLOW.md @@ -1,188 +1,3 @@ # Sales Workflow -How to run a sale in TrackGo: from a request or order, through packing and invoicing, to payment. - -You need permission to view each menu. Status buttons (Process, Complete, Submit, Approve, and so on) appear only if you are allowed to edit. - ---- - -## Before you start - -Set up the records that every sales document needs: - -| You need | Where to create it | -| ----------------------------------- | ---------------------------- | -| Division, branch, customer, product | **Settings → Data** | -| Salesperson | **Sales → Data → Employees** | - -If a menu is missing, ask an administrator to give your privilege **View** (and **Update** for status buttons) on that area. - ---- - -## The usual flow - -```mermaid -flowchart LR - subgraph sales [Sales] - R[Sales Request] - O[Sales Order] - P[Process] - I[Sales Invoice] - PAY[Sales Payment] - end - subgraph logistics [Logistics] - PS[Packing Slip] - C[Complete] - end - R -.->|optional| O - O --> P - P --> I - P -->|unless you skip it| PS - PS --> C - I --> PAY -``` - -1. Optionally create and approve a **sales request**. -2. Create a **sales order** (from the request, or from scratch). -3. Open the draft order and click **Process**. Leave **Generate packing slip** checked unless you do not need delivery paperwork. Processing creates a **sales invoice**, and a **packing slip** unless you skip it. -4. If there is a packing slip, open **Logistics → Packing slips**, then **Complete** and enter how much was delivered. -5. Open the invoice and click **Create Sales Payment**. **Submit** the payment, then **Approve** it (or **Reject** / **Rollback**). - ---- - -## Sales request - -**Menu:** Sales → Activities → Sales Requests - -A request is optional. You can go straight to a sales order. - -1. Click **Create**. Fill in date, salesperson, branch, division, customer, address, and at least one product with a quantity. Product price and document code are optional. Save. -2. While the status is **Draft**, click **Submit** to send it for approval. You can also use **Change status** to mark it **Rejected**. -3. While it is **Pending**, click **Approve** or **Reject**. **Change status** can send it back to **Draft**. -4. After it is **Approved**, there is nothing more to do on the request itself. -5. On the request detail page, click **Create Sales Order**. The order form opens with the request’s customer, location, and products already filled in. - ---- - -## Sales order - -**Menu:** Sales → Activities → Sales Orders - -1. Click **Create**. Fill in the same kind of details as a request. On a new order you can pick a sales request under **Source**; that copies the request into the form. Save. A new order starts as **Draft**. -2. On a **Draft** order, click **Process**. - - You will see: _Processing creates a sales invoice and, unless skipped, a packing slip._ - - **Generate packing slip** is checked by default. Uncheck it if you do not want a packing slip. -3. On **Draft** or **Processed**, you can **Cancel**. There is no **Complete** button on orders. If the order later shows **Completed**, that was not something you clicked on this screen. -4. On the order detail page you can see linked packing slips and invoices, and click **Create Sales Invoice**. - -You can select several orders and Process or Cancel them together, as long as they are all in a status that allows that action. - ---- - -## Packing slip - -**Menu:** Logistics → Activities → Packing slips - -Packing slips live under **Logistics**, not Sales. You can also create one by hand and link it to a sales order. - -1. If the status is **Draft**, use **Change status** to move it to **Processed**, or **Cancel** it. There is no **Process** button here. -2. When it is **Processed**, click **Complete**. Enter the **delivered quantity** for each product. Remaining quantity opens a **new packing slip**. -3. You can **Cancel** a slip while it is **Draft** or **Processed**. - ---- - -## Sales invoice - -**Menu:** Sales → Activities → Sales Invoices - -Invoices appear when you **Process** an order. You can also create one yourself, optionally from an order or a packing slip. - -On the invoice, the only status button is **Cancel** (while the invoice is **Draft**, **Processed**, or **Partial**). You cannot choose Processed, Partial, or Completed yourself. Those labels can still show on the invoice. - -On the invoice detail page, click **Create Sales Payment**. The payment form opens with that invoice and its remaining balance. - ---- - -## Sales plan - -**Menu:** Sales → Activities → Sales Plans - -When you create or edit a **sales** plan, you can attach one or more invoices. Saving the plan does not change the invoice status. - -(Logistics plans attach packing slips instead.) - ---- - -## Sales payment - -**Menu:** Sales → Activities → Sales Payments - -1. Click **Create**. Enter the date and at least one line: an invoice and an amount. Images and notes are optional. Save. A new payment starts as **Draft**. -2. Click **Submit** to move it to **Pending**. You can also use **Change status** to mark it **Rejected**. -3. While it is **Pending**, click **Approve**, **Reject**, or **Rollback** (back to **Draft**). -4. After **Approved**, you cannot change the status further. A **Rejected** payment can be sent back to **Draft** with **Change status**. - -Approving a payment does not change the invoice status from this screen. Refresh the invoice if you need to see an updated balance. - ---- - -## What you can do at each status - -**Buttons** are the labelled actions on the list or detail page. **Change status** is a separate dialog that lists the statuses you may pick. Invoices do not have Change status. - -### Sales request and sales payment - -Both use Draft → Pending → Approved or Rejected. - -| Current status | Buttons | Change status | -| -------------- | ------------------------------------------------------------ | ------------------------- | -| Draft | Submit | Rejected | -| Pending | Approve, Reject. Payments also have Rollback (back to Draft) | Draft, Approved, Rejected | -| Approved | — | — | -| Rejected | — | Draft | - -### Sales order - -| Current status | Buttons | Change status | -| -------------- | --------------- | -------------------- | -| Draft | Process, Cancel | Processed, Cancelled | -| Processed | Cancel | Cancelled | -| Completed | — | — | -| Cancelled | — | — | - -**Process** always opens the packing-slip checkbox dialog (not Change status). - -### Packing slip - -| Current status | Buttons | Change status | -| -------------- | ---------------- | -------------------- | -| Draft | Cancel | Processed, Cancelled | -| Processed | Complete, Cancel | Completed, Cancelled | -| Completed | — | — | -| Cancelled | — | — | - -**Complete** always asks for delivered quantities. - -### Sales invoice - -You may see Draft, Processed, Partial, Completed, or Cancelled. - -| Current status | What you can do | -| ---------------------------- | ----------------- | -| Draft, Processed, or Partial | Cancel | -| Completed | No status buttons | -| Cancelled | No status buttons | - ---- - -## What you should not expect to click - -These are not buttons on the screens: - -- **Complete** on a sales order -- Setting an invoice to Processed, Partial, or Completed yourself -- Changing an invoice’s status by putting it on a sales plan -- Changing an invoice’s status by approving a payment -- Cancelling an order, packing slip, or invoice in one click for all related documents — **Cancel** applies only to the document you are looking at - -If a related document’s status changes after you act, open that document again to see the latest value. +This guide moved to [Sales workflow](/user/web/sales-workflow). diff --git a/apps/docs-dev/src/apps/web/index.md b/apps/docs-dev/src/apps/web/index.md index dccca4a..5b25c83 100644 --- a/apps/docs-dev/src/apps/web/index.md +++ b/apps/docs-dev/src/apps/web/index.md @@ -8,12 +8,12 @@ Use the sidebar to open **Sales** for day-to-day selling, **Logistics** for pack ## Where to find things -| Area | Menu | What you do there | -| ------------ | ---------------------- | ------------------------------------------------- | -| Sales | Sales → Activities | Requests, orders, invoices, payments, visit plans | -| Logistics | Logistics → Activities | Packing slips, delivery plans | -| Company data | Settings → Data | Divisions, branches, customers, products | -| Access | Settings → User | Users and privileges | +| Area | Menu | What you do there | +| --- | --- | --- | +| Sales | Sales → Activities | Requests, orders, invoices, payments, visit plans | +| Logistics | Logistics → Activities | Packing slips, delivery plans | +| Company data | Settings → Data | Divisions, branches, customers, products | +| Access | Settings → User | Users and privileges | If a menu item is missing, your privilege does not include **View** for that area. @@ -21,4 +21,11 @@ If a menu item is missing, your privilege does not include **View** for that are ## Guides -- [Sales workflow](/apps/web/SALES_WORKFLOW) — from a sales request or order through packing, invoicing, and payment +User guides now live under **User guides** in the sidebar: + +- [Web overview](/user/web/) +- [Set up your company](/user/web/setup) +- [Sales workflow](/user/web/sales-workflow) +- [Plans and visits](/user/web/plans) +- [Logistics](/user/web/logistics) +- [Timeline](/user/web/timeline) diff --git a/apps/docs-dev/src/index.md b/apps/docs-dev/src/index.md index fa968d1..6c0492f 100644 --- a/apps/docs-dev/src/index.md +++ b/apps/docs-dev/src/index.md @@ -2,63 +2,74 @@ layout: home hero: - name: 'Frontend Architecture' - text: 'Enterprise Monorepo' - tagline: 'A scalable, standardized foundation for Web & Desktop applications. Built for performance, consistency, and velocity.' + name: TrackGo + text: Sales and logistics guides + tagline: How operators, sales, and drivers use TrackGo on the web and on mobile. actions: - theme: brand - text: Get Started - link: /setup + text: User guides + link: /user/ - theme: alt - text: View Architecture - link: /overview + text: Web + link: /user/web/ features: - - title: 🧩 App Layout Engine - details: Core App Shell wrapping Mantine for rapid, consistent layout creation across all products. - link: /packages/ui/CORE-APP-SHELL - linkText: Explore App Shell - - title: 📝 Form Primitives - details: RHF + Zod + Mantine components designed for O(1) render cost and deep type safety. - link: /packages/ui/FORM-COMPONENTS - linkText: View Forms - - title: 🖥️ Desktop Ecosystem - details: Complete Electron integration with secure Inter-Process Communication (IPC) and Bridge Architecture. - link: /apps/desktop/ - linkText: Desktop Docs - - title: 🔌 Core Architecture - details: Robust state management, Event Bus, first-class i18n, and unified Storage layers. - link: /packages/core-api/ - linkText: Explore Core + - title: Web + details: Set up company data, users, plans, invoices, payments, packing slips, and activity history. + link: /user/web/ + linkText: Web guides + - title: Mobile + details: Check in at a branch, follow today's plan, visit customers, and collect payments in the field. + link: /user/mobile/ + linkText: Mobile guides + - title: Sales + details: Move from a sales request or order through invoicing and payment. + link: /user/web/sales-workflow + linkText: Sales workflow + - title: Plans + details: Create a one-off daily plan, or generate plans from weekly visit cycles. + link: /user/web/plans + linkText: Plans and visits --- + +
-

Why this Monorepo Exists

-

Building high-end enterprise applications requires strict consistency, shared tooling, and well-defined boundaries. This monorepo serves as the absolute source of truth for our frontend ecosystem.

+

How TrackGo is used

+

Operators prepare master data and daily plans on the web. Sales and drivers check in on mobile, then work the plan: visit customers, collect invoices, or complete deliveries.

- +
-

Unified Tooling

-

By enforcing strict linting, formatting, and building patterns at the root (powered by Turborepo), we ensure that every application in the ecosystem adheres to our high standards without duplicate configuration.

+

Sales on the web

+

Create requests, orders, invoices, and payments. Attach invoices to a sales plan so field staff know what to collect.

- +
-

Shared Domain Logic

-

The separation of UI components and Core logic guarantees that our web and desktop applications all share the exact same state management and event-driven architecture, drastically reducing cognitive load.

+

Logistics on the web

+

Manage packing slips and delivery plans. Complete delivered quantities so orders can finish.

- +
-

Accelerated Velocity

-

With a rich library of 22+ advanced Form components, pre-configured Vite/TypeScript environments, and an enterprise App Shell, teams can stop reinventing the wheel and start building product features on day one.

+

Field work on mobile

+

Clock in at the plan start branch, open today's destinations, check in to a customer, and record a payment.

+
+
+
+ +
+

Activity history

+

Review a day's footprints and field events on Timeline. Live map streaming on the web is Coming soon.

diff --git a/apps/docs-dev/src/packages/ui/CORE-APP-SHELL.md b/apps/docs-dev/src/packages/ui/CORE-APP-SHELL.md index 77a3330..b5f0edc 100644 --- a/apps/docs-dev/src/packages/ui/CORE-APP-SHELL.md +++ b/apps/docs-dev/src/packages/ui/CORE-APP-SHELL.md @@ -37,7 +37,7 @@ outline: [2, 3] ## Overview -The **Core App Shell** is a configuration-driven layout engine that wraps Mantine's `AppShell` component. It provides a single `` component that renders enterprise-grade application frames — complete with headers, sidebars, aside panels, utility bars, and footers — controlled entirely through a declarative `config` object and slot-based content injection. +The **Core App Shell** is a configuration-driven layout engine that wraps Mantine's `AppShell` component. It provides a single `CoreAppShell` component that renders enterprise-grade application frames — complete with headers, sidebars, aside panels, utility bars, and footers — controlled entirely through a declarative `config` object and slot-based content injection. Key capabilities: @@ -60,7 +60,7 @@ The layout engine uses a **Provider → Inner** composition pattern: CoreAppShell (Public API) └── CoreAppShellProvider (Context — state management) └── CoreAppShellInner (Layout rendering — consumes context) - └── Mantine (CSS Grid engine) + └── Mantine AppShell (CSS Grid engine) ├── AppShell.Header ← slots.utilityBar + slots.header ├── AppShell.Navbar ← slots.sidebar | slots.sidebarRail + slots.sidebarPanel ├── AppShell.Main ← children @@ -120,7 +120,7 @@ type LayoutVariant = 'header-first' | 'sidebar-first' | 'top-nav'; | `top-nav` | `default` | Header-only layout with **no visible desktop sidebar**. The sidebar is hidden on desktop but remains accessible as a mobile drawer on small screens. Ideal for documentation sites or marketing pages. | > [!IMPORTANT] -> When `variant` is set to `top-nav`, the desktop navbar is visually hidden via `collapsed.desktop: true` and width `0`. However, the `` DOM element remains mounted with responsive width props so the mobile drawer continues to function. This is an intentional design choice to avoid conditional DOM removal. +> When `variant` is set to `top-nav`, the desktop navbar is visually hidden via `collapsed.desktop: true` and width `0`. However, the `AppShell.Navbar` DOM element remains mounted with responsive width props so the mobile drawer continues to function. This is an intentional design choice to avoid conditional DOM removal. --- @@ -201,7 +201,7 @@ interface CoreAppShellSlots { | Slot | Location | Notes | | --------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | `utilityBar` | Above the header, hidden on mobile (`display: none` below `sm`) | Typically used for environment banners, announcements, or top-level links. | -| `header` | Main application header | Must contain its own `` for mobile toggle (use `useCoreAppShell()` context). | +| `header` | Main application header | Must contain its own `Burger` for mobile toggle (use `useCoreAppShell()` context). | | `sidebar` | Desktop navbar body (single-sidebar mode) | Ignored when `withDoubleSidebar` is `true` — use `sidebarRail` + `sidebarPanel` instead. | | `sidebarMobile` | Mobile drawer content | Falls back to `sidebar` if not provided. Use this to render a simplified mobile-specific navigation. | | `sidebarRail` | Narrow icon rail (double-sidebar mode) | Only rendered when `withDoubleSidebar` is `true`. Separated from `sidebarPanel` by a 1px border. | @@ -233,7 +233,7 @@ import { useCoreAppShell } from '@repo/ui/components'; | `toggleNavbarPanel()` | `() => void` | Toggle the double-sidebar panel open/closed | | `setSidebarVariant()` | `(variant: SidebarVariant) => void` | Programmatically set the sidebar to `'expanded'`, `'mini'`, or `'hidden'` | -> [!WARNING] > `useCoreAppShell()` **must** be called from within a `` subtree. Calling it outside the provider will throw: `"useCoreAppShell must be used within CoreAppShellProvider"`. If you need context access in the header slot, pass a component (not inline JSX) so it mounts inside the provider tree. +> [!WARNING] > `useCoreAppShell()` **must** be called from within a `CoreAppShell` subtree. Calling it outside the provider will throw: `"useCoreAppShell must be used within CoreAppShellProvider"`. If you need context access in the header slot, pass a component (not inline JSX) so it mounts inside the provider tree. --- @@ -416,8 +416,9 @@ function App() { } ``` -> [!NOTE] -> When `withDoubleSidebar` is `true`, the `sidebar` slot is ignored on desktop. The navbar renders `sidebarRail` (fixed-width icon column) and `sidebarPanel` (collapsible contextual panel) side-by-side. On mobile, `sidebarMobile` takes priority, falling back to `sidebar` if not provided. +::: info +When `withDoubleSidebar` is `true`, the `sidebar` slot is ignored on desktop. The navbar renders `sidebarRail` (fixed-width icon column) and `sidebarPanel` (collapsible contextual panel) side-by-side. On mobile, `sidebarMobile` takes priority, falling back to `sidebar` if not provided. +::: --- @@ -458,7 +459,7 @@ function ShellDemo() { ## CorePageContainer -A companion component for structuring page-level content within the `` area. It provides a sticky page header and a contained, padded content region. +A companion component for structuring page-level content within the `AppShell.Main` area. It provides a sticky page header and a contained, padded content region. ```tsx import { CorePageContainer } from '@repo/ui/components'; @@ -508,7 +509,7 @@ interface CorePageContainerProps extends ContainerProps { ### Mobile Navbar Lifecycle -The `` DOM element is **always mounted**, even when the layout variant is `top-nav`. The desktop content is hidden via `visibleFrom="sm"` and mobile content via `hiddenFrom="sm"`. This ensures Mantine's native drawer engine works correctly on mobile without conditional DOM removal breaking the transition animations. +The `AppShell.Navbar` DOM element is **always mounted**, even when the layout variant is `top-nav`. The desktop content is hidden via `visibleFrom="sm"` and mobile content via `hiddenFrom="sm"`. This ensures Mantine's native drawer engine works correctly on mobile without conditional DOM removal breaking the transition animations. ### Footer Positioning in `header-first` Mode diff --git a/apps/docs-dev/src/user/index.md b/apps/docs-dev/src/user/index.md new file mode 100644 index 0000000..4709d66 --- /dev/null +++ b/apps/docs-dev/src/user/index.md @@ -0,0 +1,60 @@ +# What is TrackGo + +TrackGo is a sales and logistics platform. Office staff run the **web** app. Sales, drivers, and crew work from the **mobile** app. + +You set up the company, people, products, and customers first. Then you plan the day's visits, attach invoices or packing slips, and follow field activity. + +## Who uses it + +| Role | Where they work | Typical tasks | +| --- | --- | --- | +| Operator / admin | Web | Company data, users, privileges, plans, documents | +| Sales | Web and mobile | Requests, orders, invoices, payments, customer visits | +| Driver / crew | Web (plans) and mobile | Delivery plans, packing slips, customer stops | + +What you can open depends on the **privilege** assigned to your user. If a menu is missing, ask an administrator to grant **View** for that area. + +## The usual flow + +```plantuml +@startuml +actor Operator +actor Field as "Sales or driver" + +Operator -> Web: Set up company, users, and master data +Operator -> Web: Create cycles or a one-off plan +Operator -> Web: Attach invoices or packing slips +Field -> Mobile: Clock in at the plan start branch +Field -> Mobile: Visit customers on the plan +Field -> Mobile: Collect payment or follow packing tasks +Operator -> Web: Review documents and Timeline +@enduml +``` + +1. Add company settings, branches, divisions, customers, products, and employees. +2. Create users and privileges so each person only sees what they need. +3. Build **weekly cycles** (recurring) or a **one-off plan** for a date. Attach invoices (sales) or packing slips (logistics). +4. Field staff check in at the branch on mobile, then work the plan. +5. Sales collect payment on mobile or web. Drivers complete packing slips on the web. + +## Sales documents + +The sales path is: + +**Sales request (optional) → Sales order → Invoice → Payment** + +Processing an order can also create a packing slip for delivery. Details: [Sales workflow](/user/web/sales-workflow). + +## Web and mobile + +- [Web](/user/web/) — setup, plans, sales, logistics, timeline, CSV import +- [Mobile](/user/mobile/) — login, branch check-in, today's plan, customers, payments + +## Coming soon + +These items are not in the product yet: + +- Web **Dashboard** (the menu exists; the page is a placeholder) +- **Live** position on the web map (Timeline plays back a recorded day instead) +- Mobile **packing slip status** updates (logistics tasks are listed, not updated on the phone) +- Forgot password, remember me, and sign-up on login screens diff --git a/apps/docs-dev/src/user/mobile/check-in.md b/apps/docs-dev/src/user/mobile/check-in.md new file mode 100644 index 0000000..7a9bae0 --- /dev/null +++ b/apps/docs-dev/src/user/mobile/check-in.md @@ -0,0 +1,41 @@ + + +# Check in + +

Clock in at the plan start branch before field work

+ + +Sales and drivers **clock in at the plan start branch** before they start field work. The app does not block browsing Home, Plan, or Customers without check-in, but create-customer, customer visit check-in, sales documents, and payments stay disabled until you are on duty. + +## Before you clock in + +You need **today's plan** with a start branch. If there is no plan, Clock In is unavailable and the screen explains there is no plan for today. An operator must [create or generate the plan](/user/web/plans) on the web. + +## Clock in and out + +1. From Home, tap **Check in now** if you see **You have not checked in**, or open the check-in screen. +2. Confirm your location on the map (OpenStreetMap). Use recenter if needed. +3. Tap **Clock In Now**. The app sends GPS coordinates for the plan **start branch**. +4. While on duty, the app records location footprints in the background (the interval comes from company GPS settings). +5. Tap **Clock Out** when the shift ends. Tracking stops. + +The screen shows your name, date, coordinates, and clock-in / clock-out times. + +A circle on the map is a visual guide. The Clock In button is enabled when a plan exists and you are not already checked in — it is not blocked by standing outside that circle. + +## After check-in + +While branch attendance is open: + +- You can create a customer +- You can check in to a customer on a visit +- Sales actions (request, order, payment) also need a **customer visit** check-in for that customer + +If GPS moves too far from a customer visit, Home can show a checkout warning so you can check out of the visit. + +## Coming soon + +- Check-in by **NFC** or **QR** (the screen always uses GPS) +- Enforcing the check-in radius before Clock In is enabled diff --git a/apps/docs-dev/src/user/mobile/daily-work.md b/apps/docs-dev/src/user/mobile/daily-work.md new file mode 100644 index 0000000..3737256 --- /dev/null +++ b/apps/docs-dev/src/user/mobile/daily-work.md @@ -0,0 +1,84 @@ + + +# Daily work + +

Home, Plan, and Customers after you are on duty

+ + +After [branch check-in](/user/mobile/check-in), use Home, Plan, and Customers to work the day. + +## Home + +Home has two tabs: **Plan** and **Timeline**. + +**Plan tab** + +- Greeting and your position (Sales, Driver, or Crew) +- Banner if you have not checked in at the branch +- Today's destinations — **Open** starts a customer visit +- Active visit card with checkout +- **Today Task** — invoices (sales) or packing-slip codes (driver/crew) + +**Timeline tab** + +Today's field events grouped by customer (check-in/out, sales documents, new customers). Pull down to refresh. + +Logout is on the avatar menu. + +### Coming soon on Home + +- Work **performance** totals (customer / invoice / payment / packing counts are not shown on the screen) +- Messages and Notifications icons do nothing yet + +## Plan + +The **Plan** tab lists today's destinations. Open a stop to go to the customer visit screen. + +If a plan exists, use **Add customer to plan**: + +1. Search customers who are not already on the plan. +2. For **sales** plans, you can pick outstanding invoices to attach. +3. Confirm **Add to plan**. + +You cannot create a new daily plan on the phone — only extend an existing one. + +### Coming soon on Plan + +- Picking **packing slips** when adding a customer to a logistics plan + +## Customers + +Search and sort the list by **Name**, **Code**, or **Distance**. Tap a row for the profile. + +**Create** (FAB) is available only after branch check-in. The form includes code, name, phone, NFC ID (typed), address, map location, and optional contacts. + +### Visit a customer + +Open a destination from the plan, or open the visit route from the profile. + +1. Complete **Customer check-in (GPS)** when sales actions are locked. +2. Then you can use **Sales actions**. + +Without branch check-in you see **Branch check-in is required**. Without a visit check-in for that customer you see that you must check in to the customer. + +### Sales request and sales order + +**Create sales request** and **Create sales order (no packing)** send a document with the **first loaded product** and quantity **1**. There is no product picker or cart on the phone. + +For full line items, create the documents on the [web](/user/web/sales-workflow). + +### Payments + +Outstanding invoices on the profile/visit list have **Create payment**. + +1. Confirm invoice code, status, and balance. +2. Enter **amount** (starts at the remaining balance) and optional **notes**. +3. Record the payment. GPS is attached when available. + +Amount must be greater than zero and not more than the balance. The same branch + customer visit rules apply. + +## What drivers can do today + +Drivers and crew follow the logistics plan and see packing-slip codes on Home. **Changing packing slip status on mobile is Coming soon** — complete slips on the [web](/user/web/logistics). diff --git a/apps/docs-dev/src/user/mobile/index.md b/apps/docs-dev/src/user/mobile/index.md new file mode 100644 index 0000000..698357d --- /dev/null +++ b/apps/docs-dev/src/user/mobile/index.md @@ -0,0 +1,55 @@ + + +# Mobile overview + +

Field app for sales, drivers, and crew

+ + +The TrackGo mobile app is for **sales**, **drivers**, and **crew** in the field. Bottom tabs are **Home**, **Plan**, and **Customers**. Branch check-in is a separate screen. + +Your employee position decides which plan you get: + +| Position | Plan type | Today's tasks on Home | +| --- | --- | --- | +| Sales | Sales | Invoices on today's plan | +| Driver or crew | Logistics | Packing slip codes on today's plan | + +If the account is not linked to an employee, Home and Plan explain that the profile is not linked. + +## Sign in + +1. Open the app. +2. Enter **Employee ID** and **Password**. +3. Tap **Sign In**. + +Username rules: 3–32 characters. Password: 8–72 characters. + +## A typical day + +```plantuml +@startuml +start +:Sign in; +:Open Home or Check in; +:Clock in at the plan start branch; +:Open today's plan; +:Check in to a customer; +:Collect payment or create a sales document; +:Clock out of the visit and the branch; +stop +@enduml +``` + +1. [Check in](/user/mobile/check-in) at the branch (required before most field actions). +2. [Daily work](/user/mobile/daily-work) — plan, customers, visits, payments, Home timeline. + +## Coming soon on login + +These controls are visible but do not work yet: + +- Remember Me +- Forgot Password +- Sign in with email or phone +- Sign up diff --git a/apps/docs-dev/src/user/web/import.md b/apps/docs-dev/src/user/web/import.md new file mode 100644 index 0000000..60452ca --- /dev/null +++ b/apps/docs-dev/src/user/web/import.md @@ -0,0 +1,29 @@ + + +# Import CSV + +

Import on document lists when your privilege includes Import

+ +You can bulk-load documents from a **.csv** file on these index pages: + +| Document | Menu | +| --- | --- | +| Sales requests | Sales → Activities → Sales Requests | +| Sales orders | Sales → Activities → Sales Orders | +| Sales invoices | Sales → Activities → Sales Invoices | +| Sales payments | Sales → Activities → Sales Payments | +| Packing slips | Logistics → Activities → Packing slips | + +## How to import + +1. Open the list. +2. Click **Import CSV** (hidden if you do not have **Import** on that area). +3. Choose a `.csv` file and confirm. + +There is no separate import wizard beyond the file upload. + +## What you cannot import here + +Master data (branches, customers, products), users, privileges, cycles, and plans do **not** have an Import CSV button. Create those records in their own screens, or generate plans from cycles. diff --git a/apps/docs-dev/src/user/web/index.md b/apps/docs-dev/src/user/web/index.md new file mode 100644 index 0000000..635783e --- /dev/null +++ b/apps/docs-dev/src/user/web/index.md @@ -0,0 +1,40 @@ + + +# Web overview + +

Browser and desktop app for operators, sales, and logistics.

+ +Sign in with **Username** and **Password** on the login page. You can switch the language between English and Indonesian. + +After login, the sidebar shows only the menus your privilege allows. + +## Menus + +| Menu | Icon | What you do there | +| --- | --- | --- | +| Dashboard | | Coming soon | +| Timeline | | Play back a day's GPS footprints and field activities for sales employees | +| Sales | | Employees, cycles, requests, orders, invoices, payments, plans, reports | +| Logistics | | Drivers and crew, cycles, packing slips, plans, reports | +| Settings | | Branches, divisions, customers, products, company settings, users, privileges | + +## Suggested order + +1. [Set up your company](/user/web/setup) — master data, users, and privileges +2. [Plans and visits](/user/web/plans) — one-off plans and weekly cycles +3. [Sales workflow](/user/web/sales-workflow) — request, order, invoice, payment +4. [Logistics](/user/web/logistics) — packing slips and delivery plans +5. [Timeline](/user/web/timeline) — activity history on the map +6. [Import CSV](/user/web/import) — bulk load documents + +## Reports + +**Sales → Sales Reports** and **Logistics → Logistics Reports** show report tables from the server. If none are configured, the page says there are no reports available. + +## Status and permissions + +Most master-data records use **Draft**, **Active**, and **Archived**. Sales and logistics documents use their own statuses (see each guide). + +Buttons such as Create, Process, Submit, and Approve appear only when your privilege includes that action (**Create**, **Update**, **Delete**, or **Import**). diff --git a/apps/docs-dev/src/user/web/logistics.md b/apps/docs-dev/src/user/web/logistics.md new file mode 100644 index 0000000..8becc6f --- /dev/null +++ b/apps/docs-dev/src/user/web/logistics.md @@ -0,0 +1,74 @@ + + +# Logistics + +

Logistics menus for drivers, crew, packing slips, and delivery plans

+ +Use Logistics when you need delivery paperwork and driver routes. Sales still owns requests, orders, invoices, and payments. + +## Employees and cycles + +- **Logistics → Data → Employees** — positions **driver** and **crew** +- **Logistics → Data → Logistics Cycles** — weekly visit templates for those employees + +Generate daily plans from cycles the same way as sales. See [Plans and visits](/user/web/plans). + +## Packing slips + +

Logistics → Activities → Packing slips

+ +Packing slips are created when you **Process** a sales order with **Generate packing slip** checked. You can also create one by hand and link it to a sales order. + +Typical fields: code, date, customer, sales order, location, products, notes. + +```plantuml +@startuml +start +if (Status is Draft?) then (yes) + :Change status to Processed\nor Cancel; +endif +if (Status is Processed?) then (yes) + :Complete; + :Enter delivered quantity per product; + if (Remaining quantity?) then (yes) + :A new packing slip is created\nfor the remainder; + else (no) + :Slip is Completed; + endif +endif +stop +@enduml +``` + +1. If the status is **Draft**, use **Change status** to move it to **Processed**, or **Cancel** it. There is no **Process** button here. +2. When it is **Processed**, click **Complete**. Enter the **delivered quantity** for each product. Remaining quantity opens a **new packing slip**. +3. You can **Cancel** a slip while it is **Draft** or **Processed**. + +When every related packing slip is completed, the linked sales order can move to **Completed**. If you skip packing on the order, the order does not wait for a slip. + +### Status actions + +| Current status | Buttons | Change status | +| --- | --- | --- | +| Draft | Cancel | Processed, Cancelled | +| Processed | Complete, Cancel | Completed, Cancelled | +| Completed | — | — | +| Cancelled | — | — | + +**Complete** always asks for delivered quantities. + +You can [import packing slips from CSV](/user/web/import) if your privilege includes **Import**. + +## Logistics plans + +

Logistics → Activities → Logistics Plans

+ +Same plan model as sales: employee, date, start/end branch, customers. Attach **packing slips** instead of invoices. + +Drivers and crew open today's plan on [mobile](/user/mobile/daily-work). Home shows packing-slip codes as today's tasks. + +## Coming soon + +**Updating packing slip status on mobile** is not available. Drivers see assigned packing codes on Home; they complete slips in the web app (or an operator does). diff --git a/apps/docs-dev/src/user/web/plans.md b/apps/docs-dev/src/user/web/plans.md new file mode 100644 index 0000000..a672a1f --- /dev/null +++ b/apps/docs-dev/src/user/web/plans.md @@ -0,0 +1,68 @@ + + +# Plans and visits + +

Sales → Activities → Sales Plans, or Logistics → Activities → Logistics Plans

+ +A **plan** is one employee's work for **one date**: start branch, end branch, customers to visit, and documents to collect. + +There is no recurrence switch on the plan form. Recurring work uses **cycles**, then **Generate**. + +```plantuml +@startuml +start +if (Need a repeating weekly route?) then (yes) + :Create a cycle with weekday routes; + :Generate plans for a date range; +else (no) + :Create a one-off plan for a date; +endif +:Attach invoices (sales) or packing slips (logistics); +:Field staff open the plan on mobile; +stop +@enduml +``` + +## One-off plan + +**Create page description in the app:** "Create a one-off daily plan for an employee." + +1. Open **Sales Plans** or **Logistics Plans**. +2. Click **Create**. +3. Choose the **employee**, **date** (today or later), **start branch**, and **end branch**. +4. Add **customers** as destinations (order matters for the route). +5. After customers are selected: + - Sales plans: attach **invoices** for those customers + - Logistics plans: attach **packing slips** for those customers +6. Save. Status is **Draft**, **Active**, or **Archived** like other master records. + +You can preview customers and attached documents on the form. + +Saving a sales plan does **not** change invoice status. + +## Weekly cycles (recurring) + +

Sales → Data → Sales Cycles, or Logistics → Data → Logistics Cycles

+ +A cycle is a **weekly visit template** for one employee: cycle number and, for each weekday, whether the day is active, start/end branch, and customers. + +1. Create a cycle for the employee. +2. Enable the weekdays they work and fill the route. +3. Set the cycle to **Active**. + +## Generate plans from cycles + +On the plans list, click **Generate**. + +1. Choose the **employee**. +2. Choose **from** and **to** dates. +3. Confirm. The app creates daily plans from the cycle and reports how many were **created** and **skipped** (for example if a plan already exists). + +## Who uses the plan + +- **Web operators** create and generate plans, then attach documents. +- **Sales and drivers on mobile** see today's plan after they exist. They can add a customer to an existing plan; they cannot create a new plan on the phone. + +See [Mobile daily work](/user/mobile/daily-work). diff --git a/apps/docs-dev/src/user/web/sales-workflow.md b/apps/docs-dev/src/user/web/sales-workflow.md new file mode 100644 index 0000000..dc87f92 --- /dev/null +++ b/apps/docs-dev/src/user/web/sales-workflow.md @@ -0,0 +1,154 @@ + + +# Sales workflow + +

Sales → Activities

+ +How to run a sale: from a request or order, through packing and invoicing, to payment. + +You need permission to view each menu. Status buttons (Process, Complete, Submit, Approve, and so on) appear only if you are allowed to edit. + +## Before you start + +Set up the records that every sales document needs: + +| You need | Where to create it | +| --- | --- | +| Division, branch, customer, product | [Settings → Data](/user/web/setup) | +| Salesperson | Sales → Data → Employees | + +If a menu is missing, ask an administrator to give your privilege **View** (and **Update** for status buttons) on that area. + +## The usual flow + +```plantuml +@startuml +start +:Sales request (optional); +:Sales order (Draft); +:Process order; +fork + :Sales invoice created; +fork again + :Packing slip created\n(unless you skip it); +end fork +if (Packing slip exists?) then (yes) + :Complete delivered quantities; +endif +:Create sales payment; +:Submit then Approve; +stop +@enduml +``` + +1. Optionally create and approve a **sales request**. +2. Create a **sales order** (from the request, or from scratch). +3. Open the draft order and click **Process**. Leave **Generate packing slip** checked unless you do not need delivery paperwork. Processing creates a **sales invoice**, and a **packing slip** unless you skip it. +4. If there is a packing slip, open **Logistics → Packing slips**, then **Complete** and enter how much was delivered. +5. Open the invoice and click **Create Sales Payment**. **Submit** the payment, then **Approve** it (or **Reject** / **Rollback**). + +You can also [import CSV](/user/web/import) for requests, orders, invoices, and payments. + +## Sales request + +

Sales → Activities → Sales Requests

+ +A request is optional. You can go straight to a sales order. + +1. Click **Create**. Fill in date, salesperson, branch, division, customer, address, and at least one product with a quantity. Product price and document code are optional. Save. +2. While the status is **Draft**, click **Submit** to send it for approval. You can also use **Change status** to mark it **Rejected**. +3. While it is **Pending**, click **Approve** or **Reject**. **Change status** can send it back to **Draft**. +4. After it is **Approved**, there is nothing more to do on the request itself. +5. On the request detail page, click **Create Sales Order**. The order form opens with the request's customer, location, and products already filled in. + +## Sales order + +

Sales → Activities → Sales Orders

+ +1. Click **Create**. Fill in the same kind of details as a request. On a new order you can pick a sales request under **Source**; that copies the request into the form. Save. A new order starts as **Draft**. +2. On a **Draft** order, click **Process**. + - You will see: *Processing creates a sales invoice and, unless skipped, a packing slip.* + - **Generate packing slip** is checked by default. Uncheck it if you do not want a packing slip. +3. On **Draft** or **Processed**, you can **Cancel**. There is no **Complete** button on orders. If the order later shows **Completed**, that was not something you clicked on this screen. +4. On the order detail page you can see linked packing slips and invoices, and click **Create Sales Invoice**. + +You can select several orders and Process or Cancel them together, as long as they are all in a status that allows that action. + +## Packing slip + +Packing slips live under **Logistics**, not Sales. See [Logistics](/user/web/logistics). + +## Sales invoice + +

Sales → Activities → Sales Invoices

+ +Invoices appear when you **Process** an order. You can also create one yourself, optionally from an order or a packing slip. + +On the invoice, the only status button is **Cancel** (while the invoice is **Draft**, **Processed**, or **Partial**). You cannot choose Processed, Partial, or Completed yourself. Those labels can still show on the invoice. + +On the invoice detail page, click **Create Sales Payment**. The payment form opens with that invoice and its remaining balance. + +You can attach invoices to a [sales plan](/user/web/plans). Saving the plan does not change invoice status. + +## Sales payment + +

Sales → Activities → Sales Payments

+ +1. Click **Create**. Enter the date and at least one line: an invoice and an amount. Images and notes are optional. Save. A new payment starts as **Draft**. +2. Click **Submit** to move it to **Pending**. You can also use **Change status** to mark it **Rejected**. +3. While it is **Pending**, click **Approve**, **Reject**, or **Rollback** (back to **Draft**). +4. After **Approved**, you cannot change the status further. A **Rejected** payment can be sent back to **Draft** with **Change status**. + +Approving a payment does not change the invoice status from this screen. Refresh the invoice if you need to see an updated balance. + +Field staff can also [record a payment on mobile](/user/mobile/daily-work) from an outstanding invoice. + +## What you can do at each status + +**Buttons** are the labelled actions on the list or detail page. **Change status** is a separate dialog that lists the statuses you may pick. Invoices do not have Change status. + +### Sales request and sales payment + +Both use Draft → Pending → Approved or Rejected. + +| Current status | Buttons | Change status | +| --- | --- | --- | +| Draft | Submit | Rejected | +| Pending | Approve, Reject. Payments also have Rollback (back to Draft) | Draft, Approved, Rejected | +| Approved | — | — | +| Rejected | — | Draft | + +### Sales order + +| Current status | Buttons | Change status | +| --- | --- | --- | +| Draft | Process, Cancel | Processed, Cancelled | +| Processed | Cancel | Cancelled | +| Completed | — | — | +| Cancelled | — | — | + +**Process** always opens the packing-slip checkbox dialog (not Change status). + +### Sales invoice + +You may see Draft, Processed, Partial, Completed, or Cancelled. + +| Current status | What you can do | +| --- | --- | +| Draft, Processed, or Partial | Cancel | +| Completed | No status buttons | +| Cancelled | No status buttons | + +## What you should not expect to click + +These are not buttons on the screens: + +- **Complete** on a sales order +- Setting an invoice to Processed, Partial, or Completed yourself +- Changing an invoice's status by putting it on a sales plan +- Changing an invoice's status by approving a payment +- Cancelling an order, packing slip, or invoice in one click for all related documents — **Cancel** applies only to the document you are looking at + +If a related document's status changes after you act, open that document again to see the latest value. diff --git a/apps/docs-dev/src/user/web/setup.md b/apps/docs-dev/src/user/web/setup.md new file mode 100644 index 0000000..d45773a --- /dev/null +++ b/apps/docs-dev/src/user/web/setup.md @@ -0,0 +1,78 @@ + + +# Set up your company + +

Settings → Data and Settings → User

+ +Do this before you create plans or sales documents. Records that other screens need (branch, division, customer, product, employee) must exist first. + +## Company settings + +**Menu:** Settings → Data → Company settings + +This is a single form, not a list. Save: + +| Field | Used for | +| --- | --- | +| Cycle start date | When weekly visit cycles start counting | +| Check-in radius (meters) | How close field staff should be when checking in | +| GPS interval (seconds) | How often the mobile app records a footprint while on duty | +| Checkout warning radius (meters) | When mobile warns that the user left a customer visit | + +## Divisions, branches, customers, products + +**Menu:** Settings → Data + +Each of these is a list with Create, Detail, Edit, and Duplicate. Status is **Draft**, **Active**, or **Archived**. + +| Record | Typical fields | +| --- | --- | +| Divisions | Name, code | +| Branches | Code, name, phone, NFC ID, address, map location, division, working days and hours | +| Customers | Code, name, phone, address, map location, NFC ID; contacts on create | +| Products | Code, name, unit, price, brand | + +Pick a location on the map for branches and customers (or type latitude and longitude). + +## Employees + +Employees are split by purpose: + +| Menu | Positions | +| --- | --- | +| Sales → Data → Employees | Sales | +| Logistics → Data → Employees | Driver, crew | + +Fields: code, name, phone, position. Link a **user** to an employee later so mobile knows whether to load a sales or logistics plan. + +## Privileges + +

Settings → User → Privileges

+ +A privilege is a named access set. On the form, set **name**, **code**, and a permission matrix. For each area you can allow: + +- **View** — show the menu and open the pages +- **Create** — create and duplicate +- **Update** — edit and change status +- **Delete** — delete +- **Import** — CSV import on supported lists + +Without **View**, the sidebar hides that item. + +## Users + +

Settings → User → Users

+ +1. Click **Create**. +2. Enter **username** and **password** (password is required on create; on edit you can leave it blank to keep the current one). +3. Choose a **privilege**. +4. Optionally link an **employee** so field login maps to sales or logistics. + +Activate the user when they should be able to sign in. + +## Coming soon + +- **Remember me** on the web login form is not saved +- **Forgot password** is not available diff --git a/apps/docs-dev/src/user/web/timeline.md b/apps/docs-dev/src/user/web/timeline.md new file mode 100644 index 0000000..34c0735 --- /dev/null +++ b/apps/docs-dev/src/user/web/timeline.md @@ -0,0 +1,38 @@ + + +# Timeline + +

Timeline in the sidebar

+ +Timeline shows **one day's** recorded GPS footprints and field activities for **sales** employees. It is a playback of what the mobile app stored while the person was on duty, not a live feed. + +## How to use it + +1. Open **Timeline**. +2. Pick a **date**. +3. Optionally filter by **employee** (sales employees), or leave all employees. +4. Search activities if the list is long. +5. Switch tabs **On the way** and **Completed**. +6. Use **Playback** (play, pause, time) to move along the recorded path. The overlay **Current location** is the playback cursor, not a live GPS point. + +If there is no data for that day, the map shows that there is no timeline data. + +## What activities look like + +The list can include: + +- Branch check-in / check-out +- Customer check-in / check-out +- Sales order created +- Sales request created +- Sales payment created +- Customer created + +Footprints are recorded on mobile after branch clock-in, using the **GPS interval** in [company settings](/user/web/setup). + +## Coming soon + +- **Live** tracking of sales or drivers on the web map +- A dedicated **logistics / driver** timeline (this screen loads sales employees) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e5bb3c..59e0087 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: dayjs: specifier: ^1.11.19 version: 1.11.19 + lucide-vue-next: + specifier: ^1.0.0 + version: 1.0.0(vue@3.5.38) react: specifier: ^19.2.3 version: 19.2.3 @@ -73,6 +76,9 @@ importers: mermaid: specifier: ^11.15.0 version: 11.15.0 + plantuml-encoder: + specifier: ^1.4.0 + version: 1.4.0 typescript: specifier: 5.5.4 version: 5.5.4 @@ -1041,7 +1047,6 @@ packages: /@babel/helper-string-parser@7.29.7: resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-identifier@7.28.5: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} @@ -1050,7 +1055,6 @@ packages: /@babel/helper-validator-identifier@7.29.7: resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option@7.27.1: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} @@ -1076,7 +1080,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.29.7 - dev: true /@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5): resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} @@ -1147,7 +1150,6 @@ packages: dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - dev: true /@braintree/sanitize-url@6.0.4: resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} @@ -4791,14 +4793,12 @@ packages: entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 - dev: true /@vue/compiler-dom@3.5.38: resolution: {integrity: sha512-JTqp25l8aFfJYF7/KmsXZjAxJz7T+SjmTJLoXVjHtc2BrSgSiW2n9Aem/cWq1OPe68A8JL06B3eVdhlP0H4TVw==} dependencies: '@vue/compiler-core': 3.5.38 '@vue/shared': 3.5.38 - dev: true /@vue/compiler-sfc@3.5.38: resolution: {integrity: sha512-DuA2GiZawSEW442iw/9+Fkol8hTgb4Ke5KkhmSry65QA7YuyMbIdy8p0XZRMvNwJdgRz307W8g1CSzdvS4nuNg==} @@ -4812,14 +4812,12 @@ packages: magic-string: 0.30.21 postcss: 8.5.15 source-map-js: 1.2.1 - dev: true /@vue/compiler-ssr@3.5.38: resolution: {integrity: sha512-7s+W5Gc42FGxZMcuwl8H5B29T8BJPMdBT7KHFE+BbAuZ/iTEdTtv7z2XiMjiaUUw4w3ZcCEdHs36RuYJ2VA7bA==} dependencies: '@vue/compiler-dom': 3.5.38 '@vue/shared': 3.5.38 - dev: true /@vue/devtools-api@7.7.9: resolution: {integrity: sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==} @@ -4849,14 +4847,12 @@ packages: resolution: {integrity: sha512-pG6LV/NDNRbKizcUjFFLAfjaL8mcv4DmR9avNcUw2gDHBzZneuS2TWCmp633ynzxz9YYKNeEPK2I8Wraqy2HUQ==} dependencies: '@vue/shared': 3.5.38 - dev: true /@vue/runtime-core@3.5.38: resolution: {integrity: sha512-iyW8WVfF1CpCXxncZY5Ei6rSd6oZr5DgEom//fUjRBRl56AXPD+s9ATvukRt77ZFTuYlnVA1bxY+dJB94tWVYw==} dependencies: '@vue/reactivity': 3.5.38 '@vue/shared': 3.5.38 - dev: true /@vue/runtime-dom@3.5.38: resolution: {integrity: sha512-apX2wt9sdfDshS+a2xueFZLVpt0GkRJZSoPmrW/SA4yzXTznhfcMVW59gr7h4YQeY0vJhdJkk2rsIDwgfFgC5A==} @@ -4865,7 +4861,6 @@ packages: '@vue/runtime-core': 3.5.38 '@vue/shared': 3.5.38 csstype: 3.2.3 - dev: true /@vue/server-renderer@3.5.38(vue@3.5.38): resolution: {integrity: sha512-vue8vbf2QlV4quHqzwmJy6dWfmRhP1J8l4wtZg60CL6VoKqcPY2oe7may3+1d9qfpedjK5PRLFqd5k3Isj9mUw==} @@ -4875,11 +4870,9 @@ packages: '@vue/compiler-ssr': 3.5.38 '@vue/shared': 3.5.38 vue: 3.5.38(typescript@5.5.4) - dev: true /@vue/shared@3.5.38: resolution: {integrity: sha512-FTW0AFZNaK5/mOqvGBwVfUlNLU38TiQn4+DQgIFUnrBBJQ1crMJ82yeGQLV5jyKFsO8yRukpbuP7x+nRbH6aug==} - dev: true /@vueuse/core@12.8.2(typescript@5.5.4): resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} @@ -6733,7 +6726,6 @@ packages: /entities@7.0.1: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} - dev: true /env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} @@ -7442,7 +7434,6 @@ packages: /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true /estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -9007,6 +8998,15 @@ packages: react: 19.2.3 dev: false + /lucide-vue-next@1.0.0(vue@3.5.38): + resolution: {integrity: sha512-V6SPvx1IHTj/UY+FrIYWV5faISsPSb8BnWSFDxAtezWKvWc9ZZ40PDrdu1/Qb5vg4lHWr1hs1BAMGVGm6V1Xdg==} + deprecated: Package deprecated. Please use @lucide/vue instead. + peerDependencies: + vue: '>=3.0.1' + dependencies: + vue: 3.5.38(typescript@5.5.4) + dev: false + /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -9661,7 +9661,6 @@ packages: resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /napi-postinstall@0.3.4: resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} @@ -10117,6 +10116,10 @@ packages: engines: {node: '>=12'} dev: false + /plantuml-encoder@1.4.0: + resolution: {integrity: sha512-sxMwpDw/ySY1WB2CE3+IdMuEcWibJ72DDOsXLkSmEaSzwEUaYBT6DWgOfBiHGCux4q433X6+OEFWjlVqp7gL6g==} + dev: true + /playwright-core@1.62.1: resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} engines: {node: '>=20'} @@ -10170,7 +10173,6 @@ packages: nanoid: 3.3.15 picocolors: 1.1.1 source-map-js: 1.2.1 - dev: true /postcss@8.5.3: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} @@ -12718,7 +12720,6 @@ packages: '@vue/server-renderer': 3.5.38(vue@3.5.38) '@vue/shared': 3.5.38 typescript: 5.5.4 - dev: true /vuvuzela@1.0.3: resolution: {integrity: sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ==}