adserver-dashboard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ci/staging.yml +191 -0
- package/.dockerignore +117 -0
- package/.env +40 -0
- package/.env.staging +38 -0
- package/.gitlab-ci.yml +16 -0
- package/DEMO_STATUS.md +579 -0
- package/Dockerfile +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/index.html +17 -0
- package/Influence-MW-AdServer-12-02-2026/client/public/favicon.png +0 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/App.tsx +91 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/advanced-map-drawer.tsx +1131 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ai-recommendation-panel.tsx +379 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/app-sidebar.tsx +183 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/auto-optimize-button.tsx +184 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/availability-drawer.tsx +385 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/brand-insights-panel.tsx +87 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-agency-drawer.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-brand-drawer.tsx +275 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/creative-assignment.tsx +526 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table-toolbar.tsx +148 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table.tsx +158 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/filter-drawer.tsx +356 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/form-insights-panel.tsx +82 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/geography-selector.tsx +699 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/header-user-menu.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/history-drawer.tsx +313 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-availability-section.tsx +176 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-format-drawer.tsx +173 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-selector.tsx +401 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/manual-inventory-drawer.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/mapbox-map.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/market-insights-panel.tsx +202 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/media-owner-drawer.tsx +217 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/metric-card.tsx +58 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/page-header.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/player-status-indicator.tsx +137 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/poi-targeting-drawer.tsx +298 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommendation-score-badge.tsx +102 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommended-inventories-panel.tsx +248 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/searchable-combobox.tsx +134 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/signal-visualizations.tsx +407 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/status-badge.tsx +35 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-provider.tsx +73 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-toggle.tsx +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/traffic-slider.tsx +75 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/accordion.tsx +56 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert-dialog.tsx +139 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert.tsx +59 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/aspect-ratio.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/avatar.tsx +51 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/badge.tsx +38 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/breadcrumb.tsx +115 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/button.tsx +62 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/calendar.tsx +68 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/card.tsx +85 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/carousel.tsx +260 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/chart.tsx +365 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/checkbox.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/collapsible.tsx +11 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/command.tsx +151 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/context-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dialog.tsx +122 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/drawer.tsx +118 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dropdown-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/form.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/hover-card.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input-otp.tsx +69 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input.tsx +23 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/label.tsx +24 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/menubar.tsx +256 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/navigation-menu.tsx +128 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/pagination.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/popover.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/progress.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/radio-group.tsx +42 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/resizable.tsx +45 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/scroll-area.tsx +46 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/select.tsx +160 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/separator.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sheet.tsx +140 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sidebar.tsx +727 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/skeleton.tsx +15 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/slider.tsx +26 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/switch.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/table.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tabs.tsx +53 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/textarea.tsx +22 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toast.tsx +127 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toaster.tsx +33 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle-group.tsx +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle.tsx +43 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tooltip.tsx +30 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/vendor-stores-modal.tsx +336 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-drawer.tsx +359 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-selector.tsx +436 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-mobile.tsx +19 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-toast.ts +191 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/index.css +244 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/queryClient.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/utils.ts +39 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/venue-taxonomy.ts +532 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/main.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/assign-creative.tsx +781 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/content-hub.tsx +995 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/custom-pois.tsx +431 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/dashboard.tsx +620 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-detail.tsx +1062 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-form.tsx +1570 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deals.tsx +716 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/edit-creative-assignment.tsx +1051 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/geotargeting.tsx +675 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/integrations.tsx +425 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-creatives.tsx +622 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-form.tsx +3132 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-items.tsx +530 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/not-found.tsx +21 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play-upload.tsx +479 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play.tsx +880 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/reports.tsx +235 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/settings.tsx +652 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signal-form.tsx +1117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signals.tsx +366 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/tags.tsx +332 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/venues.tsx +381 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/mapbox-gl-draw.d.ts +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/react-simple-maps.d.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/components.json +20 -0
- package/Influence-MW-AdServer-12-02-2026/docs/PRD.md +3373 -0
- package/Influence-MW-AdServer-12-02-2026/docs/influence-feature-mapping.csv +498 -0
- package/Influence-MW-AdServer-12-02-2026/drizzle.config.ts +14 -0
- package/Influence-MW-AdServer-12-02-2026/package-lock.json +9672 -0
- package/Influence-MW-AdServer-12-02-2026/package.json +118 -0
- package/Influence-MW-AdServer-12-02-2026/postcss.config.js +6 -0
- package/Influence-MW-AdServer-12-02-2026/replit.md +91 -0
- package/Influence-MW-AdServer-12-02-2026/script/build.ts +67 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-miro-diagrams.cjs +318 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-remaining-diagrams.cjs +270 -0
- package/Influence-MW-AdServer-12-02-2026/server/index.ts +103 -0
- package/Influence-MW-AdServer-12-02-2026/server/recommendation-service.ts +319 -0
- package/Influence-MW-AdServer-12-02-2026/server/routes.ts +1890 -0
- package/Influence-MW-AdServer-12-02-2026/server/static.ts +19 -0
- package/Influence-MW-AdServer-12-02-2026/server/storage.ts +2058 -0
- package/Influence-MW-AdServer-12-02-2026/server/vite.ts +58 -0
- package/Influence-MW-AdServer-12-02-2026/shared/schema.ts +1595 -0
- package/Influence-MW-AdServer-12-02-2026/tailwind.config.ts +107 -0
- package/Influence-MW-AdServer-12-02-2026/tsconfig.json +23 -0
- package/Influence-MW-AdServer-12-02-2026/vite.config.ts +40 -0
- package/LINE_ITEM_BUDGET_FIELD_MAPPING.md +178 -0
- package/PCM/.env.example +92 -0
- package/PCM/README.md +558 -0
- package/PCM/docs/TEST_CASES.md +422 -0
- package/PCM/index.js +106 -0
- package/PCM/package-lock.json +3282 -0
- package/PCM/package.json +32 -0
- package/PCM/replit.md +64 -0
- package/PCM/schema.sql +495 -0
- package/PCM/scripts/export-schema.js +183 -0
- package/PCM/scripts/seed-comprehensive.js +631 -0
- package/PCM/scripts/seed-production.js +477 -0
- package/PCM/src/config/db.js +56 -0
- package/PCM/src/config/swagger.js +5975 -0
- package/PCM/src/dto/EmailRequestDTO.js +166 -0
- package/PCM/src/middleware/errorHandler.js +52 -0
- package/PCM/src/middleware/logger.js +26 -0
- package/PCM/src/migrations/001_add_campaign_mode_fields.sql +36 -0
- package/PCM/src/migrations/002_create_deal_id_counters.sql +22 -0
- package/PCM/src/migrations/003_update_publishers_column.sql +15 -0
- package/PCM/src/migrations/004_add_direct_dealtype_and_advertiser.sql +5 -0
- package/PCM/src/migrations/005_add_programmatic_fields_and_update_enums.sql +31 -0
- package/PCM/src/migrations/006_add_line_item_programmatic_fields.sql +12 -0
- package/PCM/src/migrations/007_add_line_item_direct_fields.sql +15 -0
- package/PCM/src/migrations/008_add_inventory_fields.sql +45 -0
- package/PCM/src/migrations/009_move_inventory_fields_to_metadata.sql +32 -0
- package/PCM/src/migrations/010_add_draft_status_and_line_items_count.sql +23 -0
- package/PCM/src/migrations/011_add_planning_field.sql +21 -0
- package/PCM/src/migrations/012_fix_inventory_composite_pk.sql +17 -0
- package/PCM/src/migrations/013_make_external_id_optional.sql +3 -0
- package/PCM/src/migrations/014_create_change_history.sql +38 -0
- package/PCM/src/migrations/016_create_publisher_insertion_orders.sql +33 -0
- package/PCM/src/migrations/017_fix_line_item_id_fk_reference.sql +86 -0
- package/PCM/src/migrations/018_create_approval_tables.sql +44 -0
- package/PCM/src/migrations/019_add_encrypted_token_column.sql +2 -0
- package/PCM/src/migrations/020_add_rejection_reason_to_deals.sql +10 -0
- package/PCM/src/migrations/021_add_publisher_external_id_to_inventories.sql +12 -0
- package/PCM/src/migrations/022_add_line_item_extended_fields.sql +24 -0
- package/PCM/src/migrations/023_add_base_price_fields.sql +8 -0
- package/PCM/src/migrations/run-migrations.js +46 -0
- package/PCM/src/models/ApprovalOTP.js +51 -0
- package/PCM/src/models/ApprovalToken.js +79 -0
- package/PCM/src/models/ChangeHistory.js +107 -0
- package/PCM/src/models/Deal.js +186 -0
- package/PCM/src/models/DealIdCounter.js +28 -0
- package/PCM/src/models/LineItem.js +227 -0
- package/PCM/src/models/LineItemCreative.js +89 -0
- package/PCM/src/models/LineItemInventory.js +115 -0
- package/PCM/src/models/PublisherInsertionOrder.js +93 -0
- package/PCM/src/models/TransactionHistory.js +34 -0
- package/PCM/src/models/associations.js +81 -0
- package/PCM/src/routes/approval.js +321 -0
- package/PCM/src/routes/creatives.js +437 -0
- package/PCM/src/routes/deals.js +1638 -0
- package/PCM/src/routes/digitalSignage.js +242 -0
- package/PCM/src/routes/insertionOrders.js +380 -0
- package/PCM/src/routes/lineItems.js +926 -0
- package/PCM/src/routes/system.js +384 -0
- package/PCM/src/services/ApprovalService.js +885 -0
- package/PCM/src/services/CampaignImportConverter.js +631 -0
- package/PCM/src/services/CampaignModeService.js +273 -0
- package/PCM/src/services/CampaignStatusService.js +395 -0
- package/PCM/src/services/ChangeHistoryService.js +316 -0
- package/PCM/src/services/DealIdService.js +94 -0
- package/PCM/src/services/DealResponseFormatter.js +90 -0
- package/PCM/src/services/EmailNotificationService.js +315 -0
- package/PCM/src/services/LineItemResponseFormatter.js +122 -0
- package/PCM/src/services/LineItemStatusService.js +380 -0
- package/PCM/src/tests/comprehensiveTestRunner.js +360 -0
- package/PCM/src/tests/comprehensiveTests.js +1277 -0
- package/PCM/src/tests/dealTypeUnitTests.js +1058 -0
- package/PCM/src/tests/testRunner.js +248 -0
- package/PCM/src/utils/caseConverter.js +92 -0
- package/PCM/src/utils/dealCalculations.js +206 -0
- package/PCM/src/utils/lineItemPayloadNormalizer.js +41 -0
- package/PCM/src/utils/payloadNormalizer.js +34 -0
- package/PCM/src/utils/sourceNormalizer.js +56 -0
- package/PCM/src/validators/creativeValidator.js +27 -0
- package/PCM/src/validators/dealValidator.js +203 -0
- package/PCM/src/validators/lineItemValidator.js +489 -0
- package/PCM/tests/approval-flows.test.js +238 -0
- package/PCM/tests/approval-workflow.test.js +291 -0
- package/PCM/tests/campaign-import-converter.test.js +543 -0
- package/PCM/tests/campaign-import-e2e.test.js +520 -0
- package/PCM/tests/campaign-status.test.js +539 -0
- package/PCM/tests/direct-publisher-split-reimport.test.js +460 -0
- package/PCM/tests/e2e/digital-signage.test.js +145 -0
- package/PCM/tests/e2e/search-filter-pagination.test.js +399 -0
- package/PCM/tests/e2e-comprehensive.test.js +3446 -0
- package/PCM/tests/edge-cases.test.js +340 -0
- package/PCM/tests/line-item-status.test.js +340 -0
- package/PCM/tests/seller-account-external-ids.test.js +877 -0
- package/PCM/tests/source-validation.test.js +324 -0
- package/PRD.md +3373 -0
- package/README.md +186 -0
- package/client/index.html +35 -0
- package/client/public/DEMO_STATUS.md +579 -0
- package/client/public/img/MW-logo-trans_1754045676555.png +0 -0
- package/client/public/locales/ar/approval.json +144 -0
- package/client/public/locales/ar/buyer.json +61 -0
- package/client/public/locales/ar/campaigns.json +1 -0
- package/client/public/locales/ar/common.json +218 -0
- package/client/public/locales/ar/contentHub.json +266 -0
- package/client/public/locales/ar/creatives.json +79 -0
- package/client/public/locales/ar/dashboard.json +57 -0
- package/client/public/locales/ar/deals.json +886 -0
- package/client/public/locales/ar/dsp.json +131 -0
- package/client/public/locales/ar/inventory.json +201 -0
- package/client/public/locales/ar/lineItems.json +553 -0
- package/client/public/locales/ar/navigation.json +48 -0
- package/client/public/locales/ar/wizard.json +1 -0
- package/client/public/locales/en/approval.json +144 -0
- package/client/public/locales/en/buyer.json +65 -0
- package/client/public/locales/en/campaigns.json +1 -0
- package/client/public/locales/en/common.json +218 -0
- package/client/public/locales/en/contentHub.json +266 -0
- package/client/public/locales/en/creatives.json +79 -0
- package/client/public/locales/en/dashboard.json +57 -0
- package/client/public/locales/en/deals.json +886 -0
- package/client/public/locales/en/dsp.json +131 -0
- package/client/public/locales/en/inventory.json +201 -0
- package/client/public/locales/en/lineItems.json +659 -0
- package/client/public/locales/en/navigation.json +48 -0
- package/client/public/locales/en/wizard.json +1 -0
- package/client/public/locales/ja/approval.json +144 -0
- package/client/public/locales/ja/buyer.json +61 -0
- package/client/public/locales/ja/campaigns.json +1 -0
- package/client/public/locales/ja/common.json +218 -0
- package/client/public/locales/ja/contentHub.json +266 -0
- package/client/public/locales/ja/creatives.json +79 -0
- package/client/public/locales/ja/dashboard.json +57 -0
- package/client/public/locales/ja/deals.json +886 -0
- package/client/public/locales/ja/dsp.json +131 -0
- package/client/public/locales/ja/inventory.json +201 -0
- package/client/public/locales/ja/lineItems.json +553 -0
- package/client/public/locales/ja/navigation.json +48 -0
- package/client/public/locales/ja/wizard.json +1 -0
- package/client/public/locales/zh/approval.json +144 -0
- package/client/public/locales/zh/buyer.json +61 -0
- package/client/public/locales/zh/campaigns.json +1 -0
- package/client/public/locales/zh/common.json +218 -0
- package/client/public/locales/zh/contentHub.json +266 -0
- package/client/public/locales/zh/creatives.json +79 -0
- package/client/public/locales/zh/dashboard.json +57 -0
- package/client/public/locales/zh/deals.json +886 -0
- package/client/public/locales/zh/dsp.json +131 -0
- package/client/public/locales/zh/inventory.json +201 -0
- package/client/public/locales/zh/lineItems.json +553 -0
- package/client/public/locales/zh/navigation.json +48 -0
- package/client/public/locales/zh/wizard.json +1 -0
- package/client/public/manifest.json +36 -0
- package/client/src/App.tsx +464 -0
- package/client/src/components/app-sidebar.tsx +312 -0
- package/client/src/components/approval/approval-decision-form.test.tsx +294 -0
- package/client/src/components/approval/approval-decision-form.tsx +326 -0
- package/client/src/components/approval/approval-sheet.tsx +631 -0
- package/client/src/components/approval/line-item-details-sheet.tsx +371 -0
- package/client/src/components/approval/otp-verification.test.tsx +337 -0
- package/client/src/components/approval/otp-verification.tsx +180 -0
- package/client/src/components/content-hub/bulk-transcode-dialog.tsx +379 -0
- package/client/src/components/content-hub/content-hub-manager-v2.tsx +574 -0
- package/client/src/components/content-hub/content-hub-manager.tsx +330 -0
- package/client/src/components/content-hub/creative-card.tsx +456 -0
- package/client/src/components/content-hub/creative-detail-sheet.tsx +685 -0
- package/client/src/components/content-hub/creative-filters.tsx +457 -0
- package/client/src/components/content-hub/creative-grid.tsx +329 -0
- package/client/src/components/content-hub/creative-selector.tsx +415 -0
- package/client/src/components/content-hub/creative-upload.tsx +547 -0
- package/client/src/components/content-hub/folder-dialogs.tsx +445 -0
- package/client/src/components/content-hub/folder-list.tsx +280 -0
- package/client/src/components/content-hub/review-dialogs.tsx +268 -0
- package/client/src/components/content-hub/transcode-dialog.tsx +226 -0
- package/client/src/components/creative-library/creative-details-view.tsx +446 -0
- package/client/src/components/creative-library/creative-filters-panel.tsx +203 -0
- package/client/src/components/creative-library/creative-list.tsx +360 -0
- package/client/src/components/creative-library/creative-status-badge.tsx +71 -0
- package/client/src/components/creative-library/folder-card.tsx +78 -0
- package/client/src/components/creative-library/index.ts +27 -0
- package/client/src/components/creative-library/new-creative-card.tsx +211 -0
- package/client/src/components/creative-library/upload-creative-dialog.tsx +261 -0
- package/client/src/components/dashboard-overview.tsx +109 -0
- package/client/src/components/deals/approval-history-panel.test.tsx +240 -0
- package/client/src/components/deals/approval-history-panel.tsx +156 -0
- package/client/src/components/deals/deal-status-badge.tsx +92 -0
- package/client/src/components/deals/import-from-planner-dialog.tsx +399 -0
- package/client/src/components/deals/market-insights-panel.tsx +237 -0
- package/client/src/components/deals/reopen-deal-sheet.tsx +191 -0
- package/client/src/components/deals/request-approval-sheet.test.tsx +323 -0
- package/client/src/components/deals/request-approval-sheet.tsx +136 -0
- package/client/src/components/deals/resend-approval-sheet.tsx +201 -0
- package/client/src/components/direct-campaigns/campaign-card.tsx +283 -0
- package/client/src/components/direct-campaigns/deal-filter-panel.tsx +325 -0
- package/client/src/components/inventory/advanced-filters-panel.tsx +273 -0
- package/client/src/components/inventory/csv-upload-modal.tsx +639 -0
- package/client/src/components/inventory/inventory-availability-view.tsx +486 -0
- package/client/src/components/inventory/inventory-details-sheet.tsx +376 -0
- package/client/src/components/inventory/inventory-map-view.tsx +596 -0
- package/client/src/components/inventory/inventory-settings-menu.tsx +52 -0
- package/client/src/components/language-switcher.tsx +53 -0
- package/client/src/components/line-items/campaign-forecast-panel.tsx +138 -0
- package/client/src/components/line-items/form-insights.tsx +89 -0
- package/client/src/components/line-items/geofencing/LocationCsvUploadDrawer.tsx +100 -0
- package/client/src/components/line-items/geofencing/POIDropdown.tsx +379 -0
- package/client/src/components/line-items/geofencing/SelectedLocationsSidebar.tsx +436 -0
- package/client/src/components/line-items/geofencing/ViewFileLocationDrawer.tsx +199 -0
- package/client/src/components/line-items/geofencing/components/ExistingFilesTab.tsx +268 -0
- package/client/src/components/line-items/geofencing/components/TemplateDownloadSection.tsx +59 -0
- package/client/src/components/line-items/geofencing/components/UploadTab.tsx +215 -0
- package/client/src/components/line-items/geofencing-map.tsx +1270 -0
- package/client/src/components/line-items/inventory-availability-section.tsx +178 -0
- package/client/src/components/line-items/line-item-schedule-manager.tsx +313 -0
- package/client/src/components/line-items/manual-inventory-drawer.tsx +346 -0
- package/client/src/components/line-items/planner-inventory-card.tsx +495 -0
- package/client/src/components/line-items/planner-schedule-grid.tsx +495 -0
- package/client/src/components/line-items/schedule-rule-editor.tsx +649 -0
- package/client/src/components/line-items/schedule-rule-types.ts +122 -0
- package/client/src/components/line-items/steps/creatives-step.tsx +681 -0
- package/client/src/components/line-items/steps/inventory-schedule-step.tsx +1596 -0
- package/client/src/components/line-items/steps/inventory-step.tsx +1533 -0
- package/client/src/components/line-items/steps/line-item-details-step.tsx +916 -0
- package/client/src/components/line-items/steps/schedule-step.tsx +273 -0
- package/client/src/components/line-items/steps/summary-step.tsx +680 -0
- package/client/src/components/line-items/steps/targeting-step.tsx +1708 -0
- package/client/src/components/product-switcher.tsx +105 -0
- package/client/src/components/protected-route.tsx +49 -0
- package/client/src/components/skip-link.tsx +22 -0
- package/client/src/components/stat-card.tsx +53 -0
- package/client/src/components/status-badge.tsx +96 -0
- package/client/src/components/ui/hierarchical-venue-selector.tsx +389 -0
- package/client/src/components/ui/toaster.tsx +111 -0
- package/client/src/contexts/auth-context.tsx +181 -0
- package/client/src/contexts/sidebar-state.tsx +50 -0
- package/client/src/contexts/theme-context.tsx +66 -0
- package/client/src/data/campaign-data.json +107 -0
- package/client/src/data/countries.json +22 -0
- package/client/src/hooks/use-approval.ts +366 -0
- package/client/src/hooks/use-keyboard-shortcuts.ts +74 -0
- package/client/src/hooks/use-media-query.ts +46 -0
- package/client/src/hooks/use-mobile.tsx +19 -0
- package/client/src/hooks/use-page-title.ts +21 -0
- package/client/src/hooks/use-toast.ts +195 -0
- package/client/src/index.css +694 -0
- package/client/src/lib/__tests__/accessibility.test.ts +104 -0
- package/client/src/lib/__tests__/date-utils.test.ts +199 -0
- package/client/src/lib/__tests__/dsp-buyer-api.test.ts +127 -0
- package/client/src/lib/__tests__/dsp-buyer-integration.test.ts +247 -0
- package/client/src/lib/__tests__/storage-utils.test.ts +167 -0
- package/client/src/lib/__tests__/utils.test.ts +57 -0
- package/client/src/lib/accessibility.ts +141 -0
- package/client/src/lib/api-config.ts +9 -0
- package/client/src/lib/auth-service.ts +209 -0
- package/client/src/lib/campaign-creative-api.ts +82 -0
- package/client/src/lib/company-api.ts +61 -0
- package/client/src/lib/content-hub-api.ts +407 -0
- package/client/src/lib/creative-mapper.ts +61 -0
- package/client/src/lib/date-utils.ts +119 -0
- package/client/src/lib/deal-helpers.ts +220 -0
- package/client/src/lib/dsp-buyer-api.ts +196 -0
- package/client/src/lib/geo-import-api.ts +151 -0
- package/client/src/lib/google-poi-api.ts +305 -0
- package/client/src/lib/i18n/__tests__/formatting.test.ts +202 -0
- package/client/src/lib/i18n/formatting.ts +130 -0
- package/client/src/lib/i18n/index.ts +8 -0
- package/client/src/lib/i18n-compat.ts +76 -0
- package/client/src/lib/influence-deals-api.ts +896 -0
- package/client/src/lib/inventory-api.ts +399 -0
- package/client/src/lib/oauth-service.ts +678 -0
- package/client/src/lib/poi-types.ts +75 -0
- package/client/src/lib/queryClient.ts +144 -0
- package/client/src/lib/recommendation-api.ts +380 -0
- package/client/src/lib/storage-utils.ts +104 -0
- package/client/src/lib/tolgee.ts +85 -0
- package/client/src/lib/utils.ts +0 -0
- package/client/src/main.tsx +67 -0
- package/client/src/mapbox-draw-modes.d.ts +32 -0
- package/client/src/pages/all-folders.tsx +203 -0
- package/client/src/pages/auth-callback.tsx +115 -0
- package/client/src/pages/buyer-form.tsx +339 -0
- package/client/src/pages/buyer-list.tsx +622 -0
- package/client/src/pages/content-hub.tsx +1358 -0
- package/client/src/pages/create-deal.tsx +2093 -0
- package/client/src/pages/creative-assignment-page.tsx +548 -0
- package/client/src/pages/creatives.tsx +5 -0
- package/client/src/pages/custom-pois.tsx +425 -0
- package/client/src/pages/dashboard.tsx +615 -0
- package/client/src/pages/deal-history.tsx +434 -0
- package/client/src/pages/deal-line-items.tsx +1703 -0
- package/client/src/pages/demo-status.tsx +113 -0
- package/client/src/pages/direct-campaign-details.tsx +361 -0
- package/client/src/pages/direct-campaigns-new.tsx +824 -0
- package/client/src/pages/dsp-form.tsx +803 -0
- package/client/src/pages/dsp-list.tsx +239 -0
- package/client/src/pages/folder-content.tsx +336 -0
- package/client/src/pages/integrations.tsx +429 -0
- package/client/src/pages/line-item-creatives.tsx +789 -0
- package/client/src/pages/line-item-detail-page.tsx +684 -0
- package/client/src/pages/line-item-form-page.tsx +3261 -0
- package/client/src/pages/line-item-wizard.tsx +1207 -0
- package/client/src/pages/login.tsx +154 -0
- package/client/src/pages/not-found.tsx +23 -0
- package/client/src/pages/proof-of-play.tsx +397 -0
- package/client/src/pages/public-approval.tsx +551 -0
- package/client/src/pages/reports.tsx +231 -0
- package/client/src/pages/settings.tsx +760 -0
- package/client/src/pages/signals.tsx +389 -0
- package/client/src/pages/tags.tsx +318 -0
- package/client/src/pages/test-results.tsx +328 -0
- package/client/src/store/hooks.ts +5 -0
- package/client/src/store/index.ts +15 -0
- package/client/src/store/mapMarkerLocationsSlice.ts +241 -0
- package/client/src/styles/design-tokens.css +324 -0
- package/client/src/test/setup.ts +261 -0
- package/client/src/test/test-utils.tsx +40 -0
- package/client/src/types/approval.ts +221 -0
- package/client/src/types/content-hub.ts +209 -0
- package/client/src/types/geofencing.ts +67 -0
- package/client/src/types/transcoding.ts +140 -0
- package/client/src/vite-env.d.ts +18 -0
- package/components.json +20 -0
- package/creative-api.json +1 -0
- package/docs/AI_REFERENCE.md +459 -0
- package/docs/MWDesign-Prompt.md +132 -0
- package/docs/MWDesign-System.md +344 -0
- package/docs/test-plan.md +277 -0
- package/e2e/AUTONOMOUS-TESTING.md +406 -0
- package/e2e/README.md +219 -0
- package/e2e/autonomous-flow.spec.ts +308 -0
- package/e2e/debug-sso.spec.ts +163 -0
- package/e2e/direct-campaigns.spec.ts +219 -0
- package/e2e/explore-sso.spec.ts +149 -0
- package/e2e/fixtures/auth.ts +26 -0
- package/e2e/fixtures/enhanced-test.ts +331 -0
- package/e2e/pagination.spec.ts +280 -0
- package/e2e/view-toggle.spec.ts +312 -0
- package/generated-icon.png +0 -0
- package/i18next-scanner.config.cjs +46 -0
- package/package.json +141 -0
- package/playwright.config.ts +93 -0
- package/postcss.config.js +6 -0
- package/replit.md +196 -0
- package/screenshot-after-login.png +0 -0
- package/screenshot-contenthub-grid.png +0 -0
- package/screenshot-contenthub-list-fixed.png +0 -0
- package/screenshot-contenthub-list.png +0 -0
- package/screenshot-create-deal.png +0 -0
- package/screenshot-dashboard.png +0 -0
- package/screenshot-deals.png +0 -0
- package/screenshot-login-filled.png +0 -0
- package/screenshot-login.png +0 -0
- package/screenshot.mjs +24 -0
- package/scripts/deploy-stg.sh +185 -0
- package/shared/direct-io-schema.ts +383 -0
- package/shared/schema.ts +439 -0
- package/shared/screen-types.ts +149 -0
- package/springdocDefault.json +1 -0
- package/swagger-ui-bundle.js +2 -0
- package/swagger-ui-init.js +10316 -0
- package/tailwind.config.ts +282 -0
- package/terraform/README.md +306 -0
- package/terraform/cloudfront.tf +289 -0
- package/terraform/ecs.tf +727 -0
- package/terraform/environments/dev.tfvars +59 -0
- package/terraform/environments/production.tfvars +60 -0
- package/terraform/main.tf +47 -0
- package/terraform/outputs.tf +145 -0
- package/terraform/s3.tf +192 -0
- package/terraform/variables.tf +226 -0
- package/terraform/waf.tf +165 -0
- package/terraform-frontend/.terraform.lock.hcl +25 -0
- package/terraform-frontend/README.md +85 -0
- package/terraform-frontend/cloudfront.tf +125 -0
- package/terraform-frontend/main.tf +31 -0
- package/terraform-frontend/outputs.tf +24 -0
- package/terraform-frontend/terraform.tfvars +12 -0
- package/terraform-frontend/variables.tf +53 -0
- package/tsconfig.json +23 -0
- package/vite.config.ts +226 -0
- package/vitest.config.ts +56 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
# AI Development Reference Specification
|
|
2
|
+
|
|
3
|
+
This document serves as the canonical reference for AI agents working on this repository. All automated code generation, testing, and documentation should follow these guidelines.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
1. [Project Overview](#project-overview)
|
|
7
|
+
2. [Repository Structure](#repository-structure)
|
|
8
|
+
3. [Coding Standards](#coding-standards)
|
|
9
|
+
4. [Testing Requirements](#testing-requirements)
|
|
10
|
+
5. [Component Patterns](#component-patterns)
|
|
11
|
+
6. [Internationalization (i18n)](#internationalization-i18n)
|
|
12
|
+
7. [Accessibility (a11y)](#accessibility-a11y)
|
|
13
|
+
8. [State Management](#state-management)
|
|
14
|
+
9. [API Integration](#api-integration)
|
|
15
|
+
10. [Definition of Done](#definition-of-done)
|
|
16
|
+
11. [AI Workflow Instructions](#ai-workflow-instructions)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Project Overview
|
|
21
|
+
|
|
22
|
+
| Aspect | Description |
|
|
23
|
+
|--------|-------------|
|
|
24
|
+
| **Type** | React Single Page Application (SPA) |
|
|
25
|
+
| **Tech Stack** | React 18, TypeScript, Vite, TailwindCSS |
|
|
26
|
+
| **UI Library** | `@moving-walls/design-system` (npm package) |
|
|
27
|
+
| **Deployment** | Static site to S3 + CloudFront |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Repository Structure
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
├── client/src/
|
|
35
|
+
│ ├── components/ # React components
|
|
36
|
+
│ ├── hooks/ # Custom React hooks
|
|
37
|
+
│ ├── lib/ # Utility functions
|
|
38
|
+
│ │ └── __tests__/ # Unit tests
|
|
39
|
+
│ ├── pages/ # Page components
|
|
40
|
+
│ ├── contexts/ # React context providers
|
|
41
|
+
│ └── locales/ # i18n translation files
|
|
42
|
+
├── shared/ # Shared TypeScript types
|
|
43
|
+
├── e2e/ # Playwright E2E tests
|
|
44
|
+
├── docs/ # Documentation
|
|
45
|
+
├── terraform/ # AWS infrastructure
|
|
46
|
+
└── .ci/ # GitLab CI/CD pipelines
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Coding Standards
|
|
52
|
+
|
|
53
|
+
### TypeScript
|
|
54
|
+
|
|
55
|
+
| Rule | Requirement |
|
|
56
|
+
|------|-------------|
|
|
57
|
+
| Strict mode | Enabled |
|
|
58
|
+
| No `any` type | Use proper typing or `unknown` |
|
|
59
|
+
| Interface naming | PascalCase, no `I` prefix |
|
|
60
|
+
| Enum naming | PascalCase for enum, UPPER_CASE for values |
|
|
61
|
+
| File naming | kebab-case for files, PascalCase for components |
|
|
62
|
+
|
|
63
|
+
### React Patterns
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// CORRECT: Functional component with explicit typing
|
|
67
|
+
interface ButtonProps {
|
|
68
|
+
variant?: 'primary' | 'secondary';
|
|
69
|
+
size?: 'sm' | 'md' | 'lg';
|
|
70
|
+
children: React.ReactNode;
|
|
71
|
+
onClick?: () => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function Button({ variant = 'primary', size = 'md', children, onClick }: ButtonProps) {
|
|
75
|
+
return (
|
|
76
|
+
<button className={cn(buttonVariants({ variant, size }))} onClick={onClick}>
|
|
77
|
+
{children}
|
|
78
|
+
</button>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// WRONG: Using React.FC (avoid)
|
|
83
|
+
// WRONG: Inline object destructuring without interface
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Import Order
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// 1. React and framework imports
|
|
90
|
+
import React, { useState, useEffect } from 'react';
|
|
91
|
+
|
|
92
|
+
// 2. Third-party libraries
|
|
93
|
+
import { useQuery } from '@tanstack/react-query';
|
|
94
|
+
import { format } from 'date-fns';
|
|
95
|
+
|
|
96
|
+
// 3. Design system components
|
|
97
|
+
import { Button, Card } from '@moving-walls/design-system';
|
|
98
|
+
|
|
99
|
+
// 4. Internal components (absolute imports)
|
|
100
|
+
import { DealCard } from '@/components/deals/deal-card';
|
|
101
|
+
|
|
102
|
+
// 5. Internal utilities
|
|
103
|
+
import { cn } from '@/lib/utils';
|
|
104
|
+
|
|
105
|
+
// 6. Types
|
|
106
|
+
import type { Deal } from '@shared/types';
|
|
107
|
+
|
|
108
|
+
// 7. Styles (if any)
|
|
109
|
+
import './styles.css';
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Allowed Libraries
|
|
113
|
+
|
|
114
|
+
| Category | Library | Usage |
|
|
115
|
+
|----------|---------|-------|
|
|
116
|
+
| UI Components | @moving-walls/design-system | Primary UI library |
|
|
117
|
+
| UI Primitives | Radix UI | Accessible primitives |
|
|
118
|
+
| Styling | TailwindCSS | Utility-first CSS |
|
|
119
|
+
| State (Server) | TanStack Query | API data fetching |
|
|
120
|
+
| State (Client) | Redux Toolkit | Complex client state (e.g., maps) |
|
|
121
|
+
| Forms | React Hook Form + Zod | Form handling and validation |
|
|
122
|
+
| Dates | date-fns | Date manipulation |
|
|
123
|
+
| i18n | i18next | Translations |
|
|
124
|
+
| Maps | Mapbox GL | Geofencing features |
|
|
125
|
+
| Routing | wouter | Client-side routing |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Testing Requirements
|
|
130
|
+
|
|
131
|
+
### Coverage Thresholds
|
|
132
|
+
|
|
133
|
+
| Metric | Threshold |
|
|
134
|
+
|--------|-----------|
|
|
135
|
+
| Statements | 80% |
|
|
136
|
+
| Branches | 75% |
|
|
137
|
+
| Functions | 80% |
|
|
138
|
+
| Lines | 80% |
|
|
139
|
+
|
|
140
|
+
### Test File Naming
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
component.tsx → component.test.tsx
|
|
144
|
+
utils.ts → utils.test.ts
|
|
145
|
+
useCustomHook.ts → useCustomHook.test.ts
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Test Structure
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
152
|
+
import { render, screen } from '@testing-library/react';
|
|
153
|
+
import userEvent from '@testing-library/user-event';
|
|
154
|
+
import { Button } from './button';
|
|
155
|
+
|
|
156
|
+
describe('Button', () => {
|
|
157
|
+
describe('rendering', () => {
|
|
158
|
+
it('should render children', () => {
|
|
159
|
+
render(<Button>Click me</Button>);
|
|
160
|
+
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('interactions', () => {
|
|
165
|
+
it('should call onClick when clicked', async () => {
|
|
166
|
+
const handleClick = vi.fn();
|
|
167
|
+
render(<Button onClick={handleClick}>Click</Button>);
|
|
168
|
+
await userEvent.click(screen.getByRole('button'));
|
|
169
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Test Commands
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `npm test` | Run all tests |
|
|
180
|
+
| `npm run test:coverage` | Run with coverage |
|
|
181
|
+
| `npm run test:watch` | Watch mode |
|
|
182
|
+
| `npm run test:e2e` | Playwright E2E tests |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Component Patterns
|
|
187
|
+
|
|
188
|
+
### Using Design System Components
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { Button, Card, CardHeader, CardContent, Badge } from '@moving-walls/design-system';
|
|
192
|
+
|
|
193
|
+
export function DealCard({ deal }: { deal: Deal }) {
|
|
194
|
+
return (
|
|
195
|
+
<Card>
|
|
196
|
+
<CardHeader>
|
|
197
|
+
<h3>{deal.name}</h3>
|
|
198
|
+
<Badge variant={deal.status === 'active' ? 'success' : 'default'}>
|
|
199
|
+
{deal.status}
|
|
200
|
+
</Badge>
|
|
201
|
+
</CardHeader>
|
|
202
|
+
<CardContent>
|
|
203
|
+
<p>{deal.description}</p>
|
|
204
|
+
<Button onClick={() => handleEdit(deal.id)}>Edit</Button>
|
|
205
|
+
</CardContent>
|
|
206
|
+
</Card>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Custom Component Pattern
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import * as React from 'react';
|
|
215
|
+
import { cn } from '@/lib/utils';
|
|
216
|
+
|
|
217
|
+
export interface CustomCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
218
|
+
variant?: 'default' | 'bordered';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const CustomCard = React.forwardRef<HTMLDivElement, CustomCardProps>(
|
|
222
|
+
({ className, variant = 'default', ...props }, ref) => {
|
|
223
|
+
return (
|
|
224
|
+
<div
|
|
225
|
+
ref={ref}
|
|
226
|
+
className={cn(
|
|
227
|
+
'rounded-lg p-4',
|
|
228
|
+
variant === 'bordered' && 'border border-gray-200',
|
|
229
|
+
className
|
|
230
|
+
)}
|
|
231
|
+
{...props}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
CustomCard.displayName = 'CustomCard';
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Internationalization (i18n)
|
|
242
|
+
|
|
243
|
+
### Supported Languages
|
|
244
|
+
|
|
245
|
+
| Code | Language | Direction |
|
|
246
|
+
|------|----------|-----------|
|
|
247
|
+
| en | English | LTR |
|
|
248
|
+
| zh | Chinese (Simplified) | LTR |
|
|
249
|
+
| ja | Japanese | LTR |
|
|
250
|
+
| ar | Arabic | RTL |
|
|
251
|
+
|
|
252
|
+
### Translation File Structure
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
client/src/locales/
|
|
256
|
+
├── en/
|
|
257
|
+
│ ├── common.json
|
|
258
|
+
│ ├── deals.json
|
|
259
|
+
│ ├── creatives.json
|
|
260
|
+
│ └── navigation.json
|
|
261
|
+
├── zh/
|
|
262
|
+
├── ja/
|
|
263
|
+
└── ar/
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Translation Keys Pattern
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"deals": {
|
|
271
|
+
"title": "Deals",
|
|
272
|
+
"createDeal": "Create Deal",
|
|
273
|
+
"form": {
|
|
274
|
+
"name": "Deal Name",
|
|
275
|
+
"budget": "Budget"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Usage in Components
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { useTranslation } from 'react-i18next';
|
|
285
|
+
|
|
286
|
+
function DealsPage() {
|
|
287
|
+
const { t } = useTranslation('deals');
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<h1>{t('title')}</h1>
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Accessibility (a11y)
|
|
298
|
+
|
|
299
|
+
### Required WCAG 2.1 AA Compliance
|
|
300
|
+
|
|
301
|
+
| Requirement | Implementation |
|
|
302
|
+
|-------------|----------------|
|
|
303
|
+
| Focus indicators | Visible focus ring on all interactive elements |
|
|
304
|
+
| Keyboard navigation | All actions accessible via keyboard |
|
|
305
|
+
| Screen reader support | Proper ARIA labels and roles |
|
|
306
|
+
| Color contrast | Minimum 4.5:1 for text |
|
|
307
|
+
| Skip links | "Skip to main content" link |
|
|
308
|
+
| Form labels | All inputs have associated labels |
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## State Management
|
|
313
|
+
|
|
314
|
+
### Server State (TanStack Query)
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
318
|
+
|
|
319
|
+
function useDeals() {
|
|
320
|
+
return useQuery({
|
|
321
|
+
queryKey: ['deals'],
|
|
322
|
+
queryFn: () => api.getDeals(),
|
|
323
|
+
staleTime: 5 * 60 * 1000,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function useCreateDeal() {
|
|
328
|
+
const queryClient = useQueryClient();
|
|
329
|
+
|
|
330
|
+
return useMutation({
|
|
331
|
+
mutationFn: (data: CreateDealInput) => api.createDeal(data),
|
|
332
|
+
onSuccess: () => {
|
|
333
|
+
queryClient.invalidateQueries({ queryKey: ['deals'] });
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Client State (Redux Toolkit)
|
|
340
|
+
|
|
341
|
+
Only use for complex client-side state like:
|
|
342
|
+
- Geofencing map state
|
|
343
|
+
- Multi-step wizard data
|
|
344
|
+
- Undo/redo functionality
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## API Integration
|
|
349
|
+
|
|
350
|
+
### API Response Pattern
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
interface ApiResponse<T> {
|
|
354
|
+
data: T;
|
|
355
|
+
status: 'success' | 'error';
|
|
356
|
+
message?: string;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
interface PaginatedResponse<T> extends ApiResponse<T[]> {
|
|
360
|
+
pagination: {
|
|
361
|
+
page: number;
|
|
362
|
+
pageSize: number;
|
|
363
|
+
total: number;
|
|
364
|
+
totalPages: number;
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Error Handling
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
try {
|
|
373
|
+
const response = await api.createDeal(data);
|
|
374
|
+
toast.success(t('deals.created'));
|
|
375
|
+
} catch (error) {
|
|
376
|
+
if (error instanceof ApiError) {
|
|
377
|
+
toast.error(error.message);
|
|
378
|
+
} else {
|
|
379
|
+
toast.error(t('errors.unexpected'));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Definition of Done
|
|
387
|
+
|
|
388
|
+
### Code Changes Checklist
|
|
389
|
+
|
|
390
|
+
- [ ] TypeScript compiles without errors
|
|
391
|
+
- [ ] All tests pass
|
|
392
|
+
- [ ] Coverage thresholds met
|
|
393
|
+
- [ ] No console.log statements (except debug builds)
|
|
394
|
+
- [ ] No hardcoded strings (use i18n)
|
|
395
|
+
- [ ] Accessibility requirements met
|
|
396
|
+
- [ ] Mobile responsive (if UI)
|
|
397
|
+
- [ ] Documentation updated (if API change)
|
|
398
|
+
|
|
399
|
+
### PR Requirements
|
|
400
|
+
|
|
401
|
+
- [ ] Descriptive commit message
|
|
402
|
+
- [ ] No merge conflicts
|
|
403
|
+
- [ ] CI/CD pipeline passes
|
|
404
|
+
- [ ] Code review approved
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## AI Workflow Instructions
|
|
409
|
+
|
|
410
|
+
### When Making Changes
|
|
411
|
+
|
|
412
|
+
1. **Read existing code** before modifying
|
|
413
|
+
2. **Follow existing patterns** in the codebase
|
|
414
|
+
3. **Run tests** after changes
|
|
415
|
+
4. **Check coverage** doesn't drop
|
|
416
|
+
5. **Update translations** for all 4 languages
|
|
417
|
+
|
|
418
|
+
### When to Defer to Humans
|
|
419
|
+
|
|
420
|
+
- Security-sensitive changes (auth, encryption)
|
|
421
|
+
- Database schema migrations
|
|
422
|
+
- API contract changes
|
|
423
|
+
- Third-party service integrations
|
|
424
|
+
- Production deployment decisions
|
|
425
|
+
|
|
426
|
+
### Updating This Document
|
|
427
|
+
|
|
428
|
+
When project conventions change:
|
|
429
|
+
1. Update this document first
|
|
430
|
+
2. Apply changes to codebase
|
|
431
|
+
3. Update replit.md if architecture changes
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Quick Reference
|
|
436
|
+
|
|
437
|
+
### Path Aliases
|
|
438
|
+
|
|
439
|
+
| Alias | Target |
|
|
440
|
+
|-------|--------|
|
|
441
|
+
| `@/*` | `./client/src/*` |
|
|
442
|
+
| `@shared/*` | `./shared/*` |
|
|
443
|
+
|
|
444
|
+
### Design System Import
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
// All components from npm package
|
|
448
|
+
import { Button, Card, Dialog, Sheet, Table } from '@moving-walls/design-system';
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Useful Commands
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
npm run dev # Start dev server
|
|
455
|
+
npm test # Run tests
|
|
456
|
+
npm run test:coverage # Coverage report
|
|
457
|
+
npm run build # Build for production
|
|
458
|
+
npm run test:e2e # E2E tests
|
|
459
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# MWDesign System - AI Prompt Template
|
|
2
|
+
|
|
3
|
+
Copy and inject this prompt at the start of your chat sessions to ensure consistent use of the MWDesign system components.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Injectable Prompt
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
You are building a React application using the MWDesign System (@moving-walls/design-system). Follow these guidelines strictly:
|
|
11
|
+
|
|
12
|
+
## Component Library
|
|
13
|
+
|
|
14
|
+
Import all components from the npm package:
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Button, Card, Input, Badge, Dialog, Sheet } from '@moving-walls/design-system';
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Core Components Reference
|
|
21
|
+
|
|
22
|
+
### Form Controls
|
|
23
|
+
- `Button` - variants: default, secondary, outline, ghost, destructive; sizes: sm, default, lg
|
|
24
|
+
- `Input` - props: type, error, disabled
|
|
25
|
+
- `Textarea` - props: rows, disabled
|
|
26
|
+
- `Checkbox`, `RadioGroup` - props: checked, onCheckedChange
|
|
27
|
+
- `Switch` - props: checked, onCheckedChange
|
|
28
|
+
- `Select`, `SelectTrigger`, `SelectValue`, `SelectContent`, `SelectItem`
|
|
29
|
+
- `DatePicker`, `Calendar`
|
|
30
|
+
|
|
31
|
+
### Display Components
|
|
32
|
+
- `Card`, `CardHeader`, `CardContent`, `CardFooter`, `CardTitle`, `CardDescription`
|
|
33
|
+
- `Badge` - variants: default, secondary, destructive, outline
|
|
34
|
+
- `Alert`, `AlertTitle`, `AlertDescription`
|
|
35
|
+
- `Avatar`, `AvatarImage`, `AvatarFallback`
|
|
36
|
+
- `Progress`, `Skeleton`, `Separator`
|
|
37
|
+
- `Table`, `TableHeader`, `TableBody`, `TableRow`, `TableHead`, `TableCell`
|
|
38
|
+
|
|
39
|
+
### Layout Components
|
|
40
|
+
- `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`
|
|
41
|
+
- `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`
|
|
42
|
+
- `ScrollArea`
|
|
43
|
+
|
|
44
|
+
### Feedback Components
|
|
45
|
+
- `Spinner` - loading indicator
|
|
46
|
+
- Use toast notifications via context
|
|
47
|
+
|
|
48
|
+
### Overlay Components
|
|
49
|
+
- `Dialog`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`, `DialogTrigger`
|
|
50
|
+
- `Sheet`, `SheetContent`, `SheetHeader`, `SheetTitle`, `SheetTrigger`
|
|
51
|
+
- `Popover`, `PopoverTrigger`, `PopoverContent`
|
|
52
|
+
- `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`, `DropdownMenuItem`
|
|
53
|
+
- `Tooltip`, `TooltipTrigger`, `TooltipContent`
|
|
54
|
+
|
|
55
|
+
### Navigation
|
|
56
|
+
- `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbSeparator`
|
|
57
|
+
|
|
58
|
+
### Icons
|
|
59
|
+
- Use `lucide-react` icons directly
|
|
60
|
+
- `import { Search, Plus, Check, ChevronDown } from 'lucide-react';`
|
|
61
|
+
|
|
62
|
+
## Key Patterns
|
|
63
|
+
|
|
64
|
+
### Button with Icon
|
|
65
|
+
```tsx
|
|
66
|
+
import { Button } from '@moving-walls/design-system';
|
|
67
|
+
import { Plus } from 'lucide-react';
|
|
68
|
+
|
|
69
|
+
<Button>
|
|
70
|
+
<Plus className="mr-2 h-4 w-4" /> Add New
|
|
71
|
+
</Button>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Dropdown Menu
|
|
75
|
+
```tsx
|
|
76
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from '@moving-walls/design-system';
|
|
77
|
+
|
|
78
|
+
<DropdownMenu>
|
|
79
|
+
<DropdownMenuTrigger asChild>
|
|
80
|
+
<Button variant="outline">Options</Button>
|
|
81
|
+
</DropdownMenuTrigger>
|
|
82
|
+
<DropdownMenuContent>
|
|
83
|
+
<DropdownMenuItem onClick={() => handleEdit()}>Edit</DropdownMenuItem>
|
|
84
|
+
<DropdownMenuSeparator />
|
|
85
|
+
<DropdownMenuItem className="text-red-600">Delete</DropdownMenuItem>
|
|
86
|
+
</DropdownMenuContent>
|
|
87
|
+
</DropdownMenu>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Dialog
|
|
91
|
+
```tsx
|
|
92
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogTrigger } from '@moving-walls/design-system';
|
|
93
|
+
|
|
94
|
+
<Dialog>
|
|
95
|
+
<DialogTrigger asChild>
|
|
96
|
+
<Button>Open Dialog</Button>
|
|
97
|
+
</DialogTrigger>
|
|
98
|
+
<DialogContent>
|
|
99
|
+
<DialogHeader>
|
|
100
|
+
<DialogTitle>Title</DialogTitle>
|
|
101
|
+
<DialogDescription>Description</DialogDescription>
|
|
102
|
+
</DialogHeader>
|
|
103
|
+
<div className="py-4">Content here</div>
|
|
104
|
+
<DialogFooter>
|
|
105
|
+
<Button variant="outline">Cancel</Button>
|
|
106
|
+
<Button>Confirm</Button>
|
|
107
|
+
</DialogFooter>
|
|
108
|
+
</DialogContent>
|
|
109
|
+
</Dialog>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Styling Guidelines
|
|
113
|
+
|
|
114
|
+
- Use Tailwind CSS classes for custom styling
|
|
115
|
+
- Dark mode: Use `dark:` prefix for dark mode styles
|
|
116
|
+
- Spacing: Follow 4pt grid (4, 8, 12, 16, 24, 32, 48px)
|
|
117
|
+
|
|
118
|
+
## DO NOT
|
|
119
|
+
|
|
120
|
+
- Do not use raw HTML elements when design system components exist
|
|
121
|
+
- Do not install additional UI libraries (no Chakra, Material UI, Ant Design, etc.)
|
|
122
|
+
- Do not create custom button/input/modal components from scratch
|
|
123
|
+
- Do not use inline styles when Tailwind classes are available
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Usage
|
|
129
|
+
|
|
130
|
+
1. Copy the content between the triple backticks above
|
|
131
|
+
2. Paste it at the beginning of your chat session
|
|
132
|
+
3. The AI will follow MWDesign conventions for all component usage
|