Vue 3 + TypeScript SPA — Full-featured order management and production workflow admin panel for the Custimoo product customization SaaS. Manages the complete order lifecycle from quote to delivery, across merchants, factories, customers, and internal staff.
- What is this?
- Tech Stack
- Architecture
- Routes & Pages
- Pinia Stores
- TypeScript Models
- TanStack Query Usage
- Modal System
- Key Features
- Permission System
- Component Library
- Getting Started
Custimoo has three frontend applications:
development_custimoo_builder_v2 — Customer-facing product customizer
development_admin_v2 — THIS REPO — Internal admin/staff panel
custimoo (backend) — Laravel 12 REST API
This panel is used by Custimoo internal staff, factory managers, order administrators, and sales reps to manage the full order lifecycle: from creating manual orders and assigning factories to tracking production status, managing invoices, and shipping.
| Package | Version | Purpose |
|---|---|---|
vue |
^3.5.13 | Core framework (Composition API, script setup) |
typescript |
^5.8.3 | Type safety |
vite |
^6.0.7 | Build tool |
vue-router |
^4.5.0 | Client-side routing (history mode) |
pinia |
^3.0.3 | State management |
pinia-plugin-persistedstate |
^4.3.0 | Persist filter state to localStorage |
@tanstack/vue-query |
^5.76.0 | Server state / data fetching |
tailwindcss |
^3.4.17 | Utility-first CSS (all components custom-built) |
lucide-vue-next |
^0.525.0 | Icon library (globally registered) |
vue-select |
^4.0.0-beta.6 | Searchable dropdown component |
vee-validate |
^4.15.0 | Form validation |
yup |
^1.6.1 | Validation schema |
axios |
^1.7.9 | HTTP client (with auth interceptor) |
date-fns |
^4.1.0 | Date calculations and formatting |
@vueuse/core |
^12.5.0 | Vue composables |
sweetalert2 |
^11.15.10 | Toast notifications + confirm dialogs |
fabric |
^6.9.1 | Canvas manipulation (production file generator) |
opentype.js |
^1.3.4 | Custom font rendering on Fabric.js canvas |
jspdf + jspdf-autotable |
^3.0.2 | Delivery notes PDF generation |
read-excel-file |
^5.8.6 | Excel roster import |
@chenfengyuan/vue-barcode |
^2.0.2 | Barcode generation |
uuid |
^11.1.0 | UUID generation |
lodash |
^4.17.21 | Utility functions |
Build targets: development, staging, sandbox, production — each with its own Vite mode and API base URL.
src/
main.ts # App bootstrap, global component + icon registration
App.vue # Root: sidebar + header + <router-view>
router/index.ts # Routes + auth guard (fetches permissions on first load)
interceptors/
axiosRequestInterceptor.ts # Bearer token from localStorage, 401 -> login redirect
store/
index.ts # useMainStore — primary global state (Pinia)
dashboard.ts # useDashboardStore — calendar/view state (Pinia)
composables/ # 15+ composables (useDashboard, useOrderDetail, useComments,
# useSharepointFiles, useOrderTimeline, useOrderActivityLogs,
# usePermissions, useDeliveryBox, useVueQuery, ...)
models/ # 130+ TypeScript interfaces (see below)
pages/ # 6 page-level components
components/
Dashboard/ # Core dashboard + 18+ modals
Shared/ # Reusable UI components (all custom Tailwind)
utils/ # Constants (order types, statuses), mappers, helpers
types/ # comments.ts, sharepoint.ts type definitions
directives/ # v-img-fallback
Auth flow: Bearer token from localStorage.getItem('access_token'). Token can also arrive as ?access_token= URL param (cleaned after extraction). On 401, redirects to VITE_VUE2_APP_URL/login (legacy Vue2 app handles login). Every request sends X-Timezone header (Intl resolved timezone).
| Route | Component | Description |
|---|---|---|
/ |
redirect | -> /dashboard |
/dashboard |
Dashboard.vue |
Main view — 3 modes: Dashboard, Calendar, My Tasks |
/delivery-box |
DeliveryBox.vue |
Packaging box dimensions catalog |
/default-categories |
DefaultCategories.vue |
Product category hierarchy management |
/resellers-management |
ResellersManagement.vue |
Reseller companies with credit/shipping status |
/order-barcode |
OrderBarcode.vue |
Barcode generation for order items |
/buying-groups-sales-reps |
BuyingGroupSalesRep.vue |
Commission and kickback records |
/:pathMatch(.*) |
redirect | 404 catch-all -> dashboard |
Route guard: router.beforeEach fetches /permissions, /navigation, and /authuser on first visit. Requires access-new-dashboard permission or redirects to login.
Manages: user, permissions, navigation (dynamic sidebar from API), lookup data (factories, orderAdmins, csManagers, salesRepresentatives, shops, companies, customers), dashboardData, dashboardTabs, dashboardRequest (persisted to localStorage), dashboardQuickFilters (persisted), loading, globalLoader, sidebarOpen.
Key actions: getDashboardData, getOrderDetail, getOrderActivityLogs, getFactories, getOrderAdmins, assignFactory, updateOrderAdmin, deleteOrder, updateOrderDQCStatus, exportOrderPrices, updateOrderUrgency, notifyCustomerForQuote, getCustomerLockerRoom, logout
Manages: currentMode (dashboard / calendar / my-tasks), currentView (day / week / month / year), events, holidays, calendarFilters, selectedCalendarDate, selectedHolidayCountryCode, orderList, selectedOrder.
Key actions: fetchCalendarData, handleEventCreated/Updated/Deleted, handleHolidayAdded/Updated/Removed, searchOrders, jumpToOrder, exportCalendarData, updateShippingDate
Organized in src/models/. Key groups:
Order domain:
Order, OrderDetail, DashboardItem, DashboardRequest, DashboardResult, TabCount (13 tab counters), OrderType (Oi/Ri/Si/R/Ci/Coi), OrderDetailItem, ShippingDateChangeLogEntry, OrderTotalPrice, OrderAdminUser
Activity / Timeline domain:
OrderActivityKind — 27 discriminated union types:
factory_assigned, factory_edited, asana_template, activity_flow, sample_upload, sample_status, customer_sample_action, sample_rejected_reupload, third_party_approval, put_in_production, production_date_change, shipping_details, shipping_address_my_task, qc_tracking_link, dropdown_status, reorder, delivery_box, details_tab_update, order_admin_assigned, urgency_updated, custom_pdf, internal_comment, price_breakdown, tech_pack, approval, schedule, dqc_status
Product / Factory domain:
Factory, FactoryProduct, FactoryPivot, Product, ProductInfo, Addon, Sku, Skucurrency, Size, Color, CustomLogo, LogoTechnology, FixedLogo, SvgGroup, TechPack, QcReport
Customer / Company domain:
User, Customer, Company, CompanyProduct, Role, CSManager, Shop, LockerRoom, LockerRoomProduct, Roster
Delivery / Shipping domain:
DeliveryNote, ShippingAddress, TrackingResponse, Bank, Country, Currency
UI domain:
DashboardTab, NavigationMenuItem, PriceInfo, ReorderData, ApiResponse, Urgency ('VIP' | 'Urgent' | 'Extra Attention')
Custom wrapper useVueQuery / useVueInfiniteQuery in src/composables/useVueQuery.ts.
| Query Key | Endpoint | Cache |
|---|---|---|
order-detail-{id} |
GET customer-orders/{id} |
staleTime: 5 min, retry: 3 |
measurement-unit-{id} |
GET get-configuration/{id}/measurement_unit |
staleTime: 10 min |
shipping-companies |
GET get-shipping-companies |
staleTime: 30 min |
sharepoint-files-{orderId}-{factoryId}-{path} |
POST order/{id}/share/point/files |
default |
order-activity-logs + itemId |
list of activity logs | default |
order-activity-log-detail + itemId + logId |
single activity log | staleTime: Infinity (cache-forever) |
| Dashboard order list | POST dashboard |
useInfiniteQuery, paginated |
Manual invalidation: useQueryClient().invalidateQueries() called after mutations that affect order state.
All modals in src/components/Dashboard/Modals/:
| Modal | Purpose |
|---|---|
CreateManualOrderModal |
Full multi-section form — merchant, customer, products, roster, logos, pricing |
PriceBreakdownModal |
Invoice status, Stripe line items, credit note creation |
ShippingDetailsModal |
Estimated shipping date + "Put in Production" flow |
AddProductModal |
Add product to existing order item |
ChangeFactoryModal |
Reassign factory per product or all items |
FactoryAssignModal |
Initial factory assignment |
AssignOrderAdminModal |
Assign order administrator |
CopyOrderModal |
Duplicate an existing order |
CreateCustomerModal |
Create new customer account |
AddInternalNoteModal |
Staff-only internal note |
MarkAsReorderModal |
Link order to original as reorder |
PutOrderOnHoldModal |
Hold with reason |
IssueStripeCreditModal |
Issue Stripe credit note |
ExportPriceModal |
Excel price export with date range |
DeliveryRequestModal |
Delivery request |
CustomTechPackModal |
Upload custom tech pack PDFs |
ProvideQuoteModal |
Set quote price for quote-type orders |
ReviewSamplesModal |
Review uploaded design samples |
DeliveryNotes |
Create/edit delivery notes with PDF export |
TimeLineModal |
Activity log detail view |
Multi-tab paginated table with 13 status tabs: pending_merchant_approval, pending_for_factory_assignment, urgent_action, customer_await, quote_requested, pending, completed, cancelled, shipped, reorders, unresolved_comments, all_items, awaiting_customer_feedback.
Features: inline actions, right-click context menu, split-pane detail view, quick filters (VIP/Urgent/Extra Attention), column sorting, search.
Visual status line rendered in OrderFlowStatusLine. 12-stage production workflow with comment threads (threaded replies, file attachments, comment resolution). Supports "on hold", "put in production", DQC approval, manual status moves with reason logging.
Custom-built calendar (day/week/month/year views). Order shipping date events, holiday overlays (country-configurable, default Denmark), drag-to-reschedule, event CRUD, Excel export.
Per-user task management with severity levels, assignee filter, order-linked tasks, tab filtering (All/Pending/Completed).
Canvas component rendering sportswear customization: SVG groups with color fills/gradients, pattern fills, logo overlays, custom text with opentype.js fonts, size spec overlays. Generates production artwork files.
File browser for Microsoft SharePoint: folder navigation, breadcrumbs, file upload (drag-and-drop), folder creation, file move/rename/delete, multi-select, thumbnails, per-factory access control.
Create PDF delivery notes with editable shipping address, box configurations (from delivery-box catalog), product line items, PDF export via jsPDF + jspdf-autotable.
Price breakdown modal shows invoice composite status: not_invoiced, partially_invoiced, invoiced, partially_paid, paid, overdue, uncollectible, manual. Links to Stripe dashboard, supports credit note issuance.
Search orders, view barcode strings per item (with size, player name, number), generate printable barcodes via JsBarcode + @chenfengyuan/vue-barcode.
Permissions fetched from /permissions and stored in Pinia. can('permission-name') composable checks membership. UI conditionally renders via v-if="can(...)".
| Permission | Controls |
|---|---|
access-new-dashboard |
Required to access this app |
manual-create-order |
Show "Create Order" button |
assign-order-administrator |
Show AssignOrderAdmin modal |
export-order-prices |
Show Export Price modal |
can-see-calendar |
Show Calendar tab |
view-my-tasks |
Show My Tasks tab |
move-order |
Enable order status movement |
update-price-breakdown |
Save button in PriceBreakdown modal |
resellers-management-edit |
Inline editing in resellers table |
shipment-booking |
Shipment Bookings button |
All custom-built with Tailwind CSS — no third-party UI framework:
| Component | Description |
|---|---|
DataTable.vue |
Sortable, searchable, paginated, sticky header, expandable rows, right-click context menu |
Dialog.vue |
Modal (sm/md/lg sizes), custom footer, keyboard close |
Calender.vue |
Fully custom calendar with Day/Week/Month/Year views (49KB) |
Select.vue |
Wrapper around vue-select |
Dropdown.vue |
Popper-based dropdown with outside-click close |
Button.vue, Switch.vue, Tabs.vue, Accordion.vue, Tooltip.vue |
Base UI components |
CommonFileUploader.vue |
Drag-and-drop file upload |
ManualRoster.vue |
Excel import + manual entry for team roster |
npm install
# Development
npm run dev # http://localhost:5173
# Staging
npm run staging
# Production build
npm run buildEnvironment variables (.env.* files per build target):
VITE_APP_BASE_URL=https://api.custimoo.com/api/
VITE_VUE2_APP_URL=https://admin.custimoo.com # login redirect| Repo | Purpose |
|---|---|
custimoo |
Laravel 12 backend API |
development_custimoo_builder_v2 |
Customer product customizer (Vue 3) |
development_admin |
Legacy Vue 2 admin panel |