Files
accounted/lib/extensions/workspace-registry.tsx
T
Jakob WennbergandClaude Opus 4.6 acb85edf4a feat: wire Zod validation into API routes, improve types and components
- Add 8 new Zod schemas (UpdateCustomer, UpdateSupplier, UpdateSupplierInvoice,
  UpdateAccount, BankUnlink, RunReconciliation, CorrectJournalEntry,
  EvaluateMappingRules) and wire validateBody() into 24 JSON-body API routes
- Remove redundant manual validation checks replaced by Zod
- Add comprehensive schema tests (222 tests)
- Improve type definitions in types/index.ts with expanded interfaces
- Refactor extension types (push-notifications, receipt-ocr) for cleaner imports
- Update transaction components (BatchCategorySelector, SwipeCategorizationView,
  QuickReviewDialog, VatTreatmentSelect) and invoice inbox workspace
- Add invoice-inbox utilities and type decoupling tests
- Fix NE-bilaga, SRU export, and invoice PDF template type usage
- Update CLAUDE.md with expanded architecture documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:00:38 +01:00

43 lines
2.4 KiB
TypeScript

import dynamic from 'next/dynamic'
import type { ComponentType } from 'react'
export interface WorkspaceComponentProps {
userId: string
}
type WorkspaceKey = `${string}/${string}`
const WORKSPACES: Record<WorkspaceKey, ComponentType<WorkspaceComponentProps>> = {
// General
'general/receipt-ocr': dynamic(() => import('@/components/extensions/general/ReceiptOcrWorkspace')),
'general/ai-categorization': dynamic(() => import('@/components/extensions/general/AiCategorizationWorkspace')),
'general/ai-chat': dynamic(() => import('@/components/extensions/general/AiChatWorkspace')),
'general/push-notifications': dynamic(() => import('@/components/extensions/general/PushNotificationsWorkspace')),
'general/invoice-inbox': dynamic(() => import('@/components/extensions/general/InvoiceInboxWorkspace')),
'general/enable-banking': dynamic(() => import('@/components/extensions/general/EnableBankingWorkspace')),
// Restaurant
'restaurant/food-cost': dynamic(() => import('@/components/extensions/restaurant/FoodCostWorkspace')),
'restaurant/earnings-per-liter': dynamic(() => import('@/components/extensions/restaurant/EarningsPerLiterWorkspace')),
'restaurant/pos-import': dynamic(() => import('@/components/extensions/restaurant/PosImportWorkspace')),
'restaurant/tip-tracking': dynamic(() => import('@/components/extensions/restaurant/TipTrackingWorkspace')),
// Construction
'construction/rot-calculator': dynamic(() => import('@/components/extensions/construction/RotCalculatorWorkspace')),
'construction/project-cost': dynamic(() => import('@/components/extensions/construction/ProjectCostWorkspace')),
// Hotel
'hotel/revpar': dynamic(() => import('@/components/extensions/hotel/RevparWorkspace')),
'hotel/occupancy': dynamic(() => import('@/components/extensions/hotel/OccupancyWorkspace')),
// Tech
'tech/billable-hours': dynamic(() => import('@/components/extensions/tech/BillableHoursWorkspace')),
'tech/project-billing': dynamic(() => import('@/components/extensions/tech/ProjectBillingWorkspace')),
// E-commerce
'ecommerce/shopify-import': dynamic(() => import('@/components/extensions/ecommerce/ShopifyImportWorkspace')),
'ecommerce/multichannel-revenue': dynamic(() => import('@/components/extensions/ecommerce/MultichannelRevenueWorkspace')),
}
export function getWorkspaceComponent(
sector: string,
slug: string
): ComponentType<WorkspaceComponentProps> | null {
return WORKSPACES[`${sector}/${slug}` as WorkspaceKey] ?? null
}