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,760 @@
|
|
|
1
|
+
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@moving-walls/design-system";
|
|
2
|
+
import { Button } from "@moving-walls/design-system";
|
|
3
|
+
import { Input } from "@moving-walls/design-system";
|
|
4
|
+
import { Label } from "@moving-walls/design-system";
|
|
5
|
+
import { Switch } from "@moving-walls/design-system";
|
|
6
|
+
import { Separator } from "@moving-walls/design-system";
|
|
7
|
+
import { Slider } from "@moving-walls/design-system";
|
|
8
|
+
import {
|
|
9
|
+
Select,
|
|
10
|
+
SelectContent,
|
|
11
|
+
SelectItem,
|
|
12
|
+
SelectTrigger,
|
|
13
|
+
SelectValue,
|
|
14
|
+
} from "@moving-walls/design-system";
|
|
15
|
+
import { Textarea } from "@moving-walls/design-system";
|
|
16
|
+
import { Settings as SettingsIcon, Bell, Shield, Globe, Palette, Save, Workflow, Languages, Package, ListFilter, Sparkles, Target, TrendingUp, Sliders } from "lucide-react";
|
|
17
|
+
import { usePageTitle } from "@/hooks/use-page-title";
|
|
18
|
+
import { useToast } from "@/hooks/use-toast";
|
|
19
|
+
import { useState } from "react";
|
|
20
|
+
|
|
21
|
+
export default function SettingsPage() {
|
|
22
|
+
usePageTitle("Settings");
|
|
23
|
+
const { toast } = useToast();
|
|
24
|
+
|
|
25
|
+
const [weights, setWeights] = useState({
|
|
26
|
+
measureFit: 15,
|
|
27
|
+
geoFit: 15,
|
|
28
|
+
availability: 15,
|
|
29
|
+
budgetFit: 10,
|
|
30
|
+
audienceFit: 15,
|
|
31
|
+
brandFit: 10,
|
|
32
|
+
qualityFit: 10,
|
|
33
|
+
timeFit: 10,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const handleSave = () => {
|
|
37
|
+
toast({
|
|
38
|
+
title: "Settings saved",
|
|
39
|
+
description: "Your settings have been updated successfully.",
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const updateWeight = (key: keyof typeof weights, value: number[]) => {
|
|
44
|
+
setWeights(prev => ({ ...prev, [key]: value[0] }));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className="h-[calc(100vh-72px)] w-full flex flex-col bg-mw-neutral-50 dark:bg-mw-neutral-900 overflow-hidden">
|
|
49
|
+
<div className="flex-shrink-0 px-6 py-4 border-b border-mw-neutral-200 bg-white dark:bg-mw-neutral-800">
|
|
50
|
+
<h1 className="text-xl font-semibold text-mw-neutral-900 dark:text-white">Settings</h1>
|
|
51
|
+
<p className="text-sm text-mw-neutral-500 dark:text-mw-neutral-400">Configure your ad server preferences</p>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex-1 overflow-auto px-6 py-6">
|
|
54
|
+
<div className="grid gap-6 max-w-4xl">
|
|
55
|
+
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle className="flex items-center gap-2">
|
|
59
|
+
<SettingsIcon className="h-5 w-5" />
|
|
60
|
+
General Settings
|
|
61
|
+
</CardTitle>
|
|
62
|
+
<CardDescription>Basic configuration for your ad server</CardDescription>
|
|
63
|
+
</CardHeader>
|
|
64
|
+
<CardContent className="pt-0 space-y-6">
|
|
65
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
66
|
+
<div className="space-y-2">
|
|
67
|
+
<Label htmlFor="company-name">Company Name</Label>
|
|
68
|
+
<Input id="company-name" defaultValue="Influence Media" />
|
|
69
|
+
</div>
|
|
70
|
+
<div className="space-y-2">
|
|
71
|
+
<Label htmlFor="timezone">Timezone</Label>
|
|
72
|
+
<Select
|
|
73
|
+
defaultValue="utc"
|
|
74
|
+
options={[
|
|
75
|
+
{ value: "utc-8", label: "UTC-8" },
|
|
76
|
+
{ value: "utc+0", label: "UTC+0" },
|
|
77
|
+
{ value: "utc+5:30", label: "UTC+5:30" },
|
|
78
|
+
{ value: "utc+8", label: "UTC+8" },
|
|
79
|
+
{ value: "utc+9", label: "UTC+9" },
|
|
80
|
+
]}
|
|
81
|
+
>
|
|
82
|
+
<SelectTrigger>
|
|
83
|
+
<SelectValue placeholder="Select timezone" />
|
|
84
|
+
</SelectTrigger>
|
|
85
|
+
<SelectContent>
|
|
86
|
+
<SelectItem value="utc-8">UTC-8</SelectItem>
|
|
87
|
+
<SelectItem value="utc+0">UTC+0</SelectItem>
|
|
88
|
+
<SelectItem value="utc+5:30">UTC+5:30</SelectItem>
|
|
89
|
+
<SelectItem value="utc+8">UTC+8</SelectItem>
|
|
90
|
+
<SelectItem value="utc+9">UTC+9</SelectItem>
|
|
91
|
+
</SelectContent>
|
|
92
|
+
</Select>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
96
|
+
<div className="space-y-2">
|
|
97
|
+
<Label htmlFor="currency">Default Currency</Label>
|
|
98
|
+
<Select
|
|
99
|
+
defaultValue="usd"
|
|
100
|
+
options={[
|
|
101
|
+
{ value: "usd", label: "USD" },
|
|
102
|
+
{ value: "myr", label: "MYR" },
|
|
103
|
+
{ value: "sgd", label: "SGD" },
|
|
104
|
+
{ value: "thb", label: "THB" },
|
|
105
|
+
{ value: "jpy", label: "JPY" },
|
|
106
|
+
]}
|
|
107
|
+
>
|
|
108
|
+
<SelectTrigger>
|
|
109
|
+
<SelectValue placeholder="Select currency" />
|
|
110
|
+
</SelectTrigger>
|
|
111
|
+
<SelectContent>
|
|
112
|
+
<SelectItem value="usd">USD</SelectItem>
|
|
113
|
+
<SelectItem value="myr">MYR</SelectItem>
|
|
114
|
+
<SelectItem value="sgd">SGD</SelectItem>
|
|
115
|
+
<SelectItem value="thb">THB</SelectItem>
|
|
116
|
+
<SelectItem value="jpy">JPY</SelectItem>
|
|
117
|
+
</SelectContent>
|
|
118
|
+
</Select>
|
|
119
|
+
</div>
|
|
120
|
+
<div className="space-y-2">
|
|
121
|
+
<Label htmlFor="date-format">Date Format</Label>
|
|
122
|
+
<Select
|
|
123
|
+
defaultValue="mdy"
|
|
124
|
+
options={[
|
|
125
|
+
{ value: "dmy", label: "DD/MM/YYYY" },
|
|
126
|
+
{ value: "mdy", label: "MM/DD/YYYY" },
|
|
127
|
+
{ value: "ymd", label: "YYYY-MM-DD" },
|
|
128
|
+
]}
|
|
129
|
+
>
|
|
130
|
+
<SelectTrigger>
|
|
131
|
+
<SelectValue placeholder="Select format" />
|
|
132
|
+
</SelectTrigger>
|
|
133
|
+
<SelectContent>
|
|
134
|
+
<SelectItem value="dmy">DD/MM/YYYY</SelectItem>
|
|
135
|
+
<SelectItem value="mdy">MM/DD/YYYY</SelectItem>
|
|
136
|
+
<SelectItem value="ymd">YYYY-MM-DD</SelectItem>
|
|
137
|
+
</SelectContent>
|
|
138
|
+
</Select>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</CardContent>
|
|
142
|
+
</Card>
|
|
143
|
+
|
|
144
|
+
<Card>
|
|
145
|
+
<CardHeader>
|
|
146
|
+
<CardTitle className="flex items-center gap-2">
|
|
147
|
+
<Bell className="h-5 w-5" />
|
|
148
|
+
Notifications
|
|
149
|
+
</CardTitle>
|
|
150
|
+
<CardDescription>Configure alert and notification preferences</CardDescription>
|
|
151
|
+
</CardHeader>
|
|
152
|
+
<CardContent className="pt-0 space-y-4">
|
|
153
|
+
<div className="flex items-center justify-between">
|
|
154
|
+
<div className="space-y-0.5">
|
|
155
|
+
<Label>Deal Alerts</Label>
|
|
156
|
+
<p className="text-sm text-muted-foreground">
|
|
157
|
+
Get notified when deals reach budget thresholds
|
|
158
|
+
</p>
|
|
159
|
+
</div>
|
|
160
|
+
<Switch defaultChecked />
|
|
161
|
+
</div>
|
|
162
|
+
<Separator />
|
|
163
|
+
<div className="flex items-center justify-between">
|
|
164
|
+
<div className="space-y-0.5">
|
|
165
|
+
<Label>Screen Status Updates</Label>
|
|
166
|
+
<p className="text-sm text-muted-foreground">
|
|
167
|
+
Alert when screens go offline or require maintenance
|
|
168
|
+
</p>
|
|
169
|
+
</div>
|
|
170
|
+
<Switch defaultChecked />
|
|
171
|
+
</div>
|
|
172
|
+
<Separator />
|
|
173
|
+
<div className="flex items-center justify-between">
|
|
174
|
+
<div className="space-y-0.5">
|
|
175
|
+
<Label>Daily Performance Reports</Label>
|
|
176
|
+
<p className="text-sm text-muted-foreground">
|
|
177
|
+
Receive daily email summaries of deal performance
|
|
178
|
+
</p>
|
|
179
|
+
</div>
|
|
180
|
+
<Switch />
|
|
181
|
+
</div>
|
|
182
|
+
<Separator />
|
|
183
|
+
<div className="flex items-center justify-between">
|
|
184
|
+
<div className="space-y-0.5">
|
|
185
|
+
<Label>Integration Status</Label>
|
|
186
|
+
<p className="text-sm text-muted-foreground">
|
|
187
|
+
Notify when SSP/DSP integrations have connectivity issues
|
|
188
|
+
</p>
|
|
189
|
+
</div>
|
|
190
|
+
<Switch defaultChecked />
|
|
191
|
+
</div>
|
|
192
|
+
</CardContent>
|
|
193
|
+
</Card>
|
|
194
|
+
|
|
195
|
+
<Card>
|
|
196
|
+
<CardHeader>
|
|
197
|
+
<CardTitle className="flex items-center gap-2">
|
|
198
|
+
<Shield className="h-5 w-5" />
|
|
199
|
+
Traffic Control
|
|
200
|
+
</CardTitle>
|
|
201
|
+
<CardDescription>Default settings for traffic allocation and delivery</CardDescription>
|
|
202
|
+
</CardHeader>
|
|
203
|
+
<CardContent className="pt-0 space-y-6">
|
|
204
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
205
|
+
<div className="space-y-2">
|
|
206
|
+
<Label htmlFor="default-allocation">Default Traffic Allocation</Label>
|
|
207
|
+
<Select
|
|
208
|
+
defaultValue="100"
|
|
209
|
+
options={[
|
|
210
|
+
{ value: "25", label: "25%" },
|
|
211
|
+
{ value: "50", label: "50%" },
|
|
212
|
+
{ value: "75", label: "75%" },
|
|
213
|
+
{ value: "100", label: "100%" },
|
|
214
|
+
]}
|
|
215
|
+
>
|
|
216
|
+
<SelectTrigger>
|
|
217
|
+
<SelectValue placeholder="Select percentage" />
|
|
218
|
+
</SelectTrigger>
|
|
219
|
+
<SelectContent>
|
|
220
|
+
<SelectItem value="25">25%</SelectItem>
|
|
221
|
+
<SelectItem value="50">50%</SelectItem>
|
|
222
|
+
<SelectItem value="75">75%</SelectItem>
|
|
223
|
+
<SelectItem value="100">100%</SelectItem>
|
|
224
|
+
</SelectContent>
|
|
225
|
+
</Select>
|
|
226
|
+
</div>
|
|
227
|
+
<div className="space-y-2">
|
|
228
|
+
<Label htmlFor="delivery-pacing">Delivery Pacing</Label>
|
|
229
|
+
<Select
|
|
230
|
+
defaultValue="even"
|
|
231
|
+
options={[
|
|
232
|
+
{ value: "even", label: "Even" },
|
|
233
|
+
{ value: "asap", label: "ASAP" },
|
|
234
|
+
{ value: "frontloaded", label: "Frontloaded" },
|
|
235
|
+
]}
|
|
236
|
+
>
|
|
237
|
+
<SelectTrigger>
|
|
238
|
+
<SelectValue placeholder="Select pacing" />
|
|
239
|
+
</SelectTrigger>
|
|
240
|
+
<SelectContent>
|
|
241
|
+
<SelectItem value="even">Even (Spread evenly)</SelectItem>
|
|
242
|
+
<SelectItem value="asap">ASAP (As fast as possible)</SelectItem>
|
|
243
|
+
<SelectItem value="frontloaded">Frontloaded (Heavy at start)</SelectItem>
|
|
244
|
+
</SelectContent>
|
|
245
|
+
</Select>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
<div className="flex items-center justify-between">
|
|
249
|
+
<div className="space-y-0.5">
|
|
250
|
+
<Label>Enable Programmatic Fallback</Label>
|
|
251
|
+
<p className="text-sm text-muted-foreground">
|
|
252
|
+
Fill unfilled inventory with programmatic demand
|
|
253
|
+
</p>
|
|
254
|
+
</div>
|
|
255
|
+
<Switch defaultChecked />
|
|
256
|
+
</div>
|
|
257
|
+
</CardContent>
|
|
258
|
+
</Card>
|
|
259
|
+
|
|
260
|
+
<Card>
|
|
261
|
+
<CardHeader>
|
|
262
|
+
<CardTitle className="flex items-center gap-2">
|
|
263
|
+
<Target className="h-5 w-5" />
|
|
264
|
+
Forecasting Defaults
|
|
265
|
+
</CardTitle>
|
|
266
|
+
<CardDescription>Configure default settings for line item forecasting</CardDescription>
|
|
267
|
+
</CardHeader>
|
|
268
|
+
<CardContent className="pt-0 space-y-6">
|
|
269
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
270
|
+
<div className="space-y-2">
|
|
271
|
+
<Label htmlFor="forecast-goal-type">Default Goal Type</Label>
|
|
272
|
+
<Select
|
|
273
|
+
defaultValue="impressions"
|
|
274
|
+
options={[
|
|
275
|
+
{ value: "impressions", label: "Impressions" },
|
|
276
|
+
{ value: "reach", label: "Reach" },
|
|
277
|
+
{ value: "sov", label: "Share of Voice" },
|
|
278
|
+
{ value: "ad-plays", label: "Ad Plays" },
|
|
279
|
+
{ value: "carbon", label: "Carbon Emission" },
|
|
280
|
+
]}
|
|
281
|
+
>
|
|
282
|
+
<SelectTrigger>
|
|
283
|
+
<SelectValue placeholder="Select goal type" />
|
|
284
|
+
</SelectTrigger>
|
|
285
|
+
<SelectContent>
|
|
286
|
+
<SelectItem value="impressions">Impressions</SelectItem>
|
|
287
|
+
<SelectItem value="reach">Reach</SelectItem>
|
|
288
|
+
<SelectItem value="sov">Share of Voice</SelectItem>
|
|
289
|
+
<SelectItem value="ad-plays">Ad Plays</SelectItem>
|
|
290
|
+
<SelectItem value="carbon">Carbon Emission</SelectItem>
|
|
291
|
+
</SelectContent>
|
|
292
|
+
</Select>
|
|
293
|
+
</div>
|
|
294
|
+
<div className="space-y-2">
|
|
295
|
+
<Label htmlFor="forecast-confidence">Confidence Level</Label>
|
|
296
|
+
<Select
|
|
297
|
+
defaultValue="medium"
|
|
298
|
+
options={[
|
|
299
|
+
{ value: "low", label: "Low 70%" },
|
|
300
|
+
{ value: "medium", label: "Medium 85%" },
|
|
301
|
+
{ value: "high", label: "High 95%" },
|
|
302
|
+
]}
|
|
303
|
+
>
|
|
304
|
+
<SelectTrigger>
|
|
305
|
+
<SelectValue placeholder="Select confidence" />
|
|
306
|
+
</SelectTrigger>
|
|
307
|
+
<SelectContent>
|
|
308
|
+
<SelectItem value="low">Low (70%)</SelectItem>
|
|
309
|
+
<SelectItem value="medium">Medium (85%)</SelectItem>
|
|
310
|
+
<SelectItem value="high">High (95%)</SelectItem>
|
|
311
|
+
</SelectContent>
|
|
312
|
+
</Select>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
316
|
+
<div className="space-y-2">
|
|
317
|
+
<Label htmlFor="default-budget-buffer">Budget Buffer (%)</Label>
|
|
318
|
+
<Input id="default-budget-buffer" type="number" defaultValue="10" />
|
|
319
|
+
<p className="text-xs text-muted-foreground">
|
|
320
|
+
Extra budget allowance for forecast variance
|
|
321
|
+
</p>
|
|
322
|
+
</div>
|
|
323
|
+
<div className="space-y-2">
|
|
324
|
+
<Label htmlFor="forecast-refresh-interval">Forecast Refresh Interval</Label>
|
|
325
|
+
<Select
|
|
326
|
+
defaultValue="daily"
|
|
327
|
+
options={[
|
|
328
|
+
{ value: "realtime", label: "Real-time" },
|
|
329
|
+
{ value: "hourly", label: "Hourly" },
|
|
330
|
+
{ value: "daily", label: "Daily" },
|
|
331
|
+
{ value: "weekly", label: "Weekly" },
|
|
332
|
+
]}
|
|
333
|
+
>
|
|
334
|
+
<SelectTrigger>
|
|
335
|
+
<SelectValue placeholder="Select interval" />
|
|
336
|
+
</SelectTrigger>
|
|
337
|
+
<SelectContent>
|
|
338
|
+
<SelectItem value="realtime">Real-time</SelectItem>
|
|
339
|
+
<SelectItem value="hourly">Hourly</SelectItem>
|
|
340
|
+
<SelectItem value="daily">Daily</SelectItem>
|
|
341
|
+
<SelectItem value="weekly">Weekly</SelectItem>
|
|
342
|
+
</SelectContent>
|
|
343
|
+
</Select>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
<div className="flex items-center justify-between">
|
|
347
|
+
<div className="space-y-0.5">
|
|
348
|
+
<Label>Include Historical Performance</Label>
|
|
349
|
+
<p className="text-sm text-muted-foreground">
|
|
350
|
+
Use historical data to improve forecast accuracy
|
|
351
|
+
</p>
|
|
352
|
+
</div>
|
|
353
|
+
<Switch defaultChecked />
|
|
354
|
+
</div>
|
|
355
|
+
</CardContent>
|
|
356
|
+
</Card>
|
|
357
|
+
|
|
358
|
+
<Card>
|
|
359
|
+
<CardHeader>
|
|
360
|
+
<CardTitle className="flex items-center gap-2">
|
|
361
|
+
<TrendingUp className="h-5 w-5" />
|
|
362
|
+
Optimization Preferences
|
|
363
|
+
</CardTitle>
|
|
364
|
+
<CardDescription>Configure AI-powered optimization behavior</CardDescription>
|
|
365
|
+
</CardHeader>
|
|
366
|
+
<CardContent className="pt-0 space-y-6">
|
|
367
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
368
|
+
<div className="space-y-2">
|
|
369
|
+
<Label htmlFor="optimization-mode">Optimization Mode</Label>
|
|
370
|
+
<Select
|
|
371
|
+
defaultValue="balanced"
|
|
372
|
+
options={[
|
|
373
|
+
{ value: "aggressive", label: "Aggressive" },
|
|
374
|
+
{ value: "balanced", label: "Balanced" },
|
|
375
|
+
{ value: "conservative", label: "Conservative" },
|
|
376
|
+
]}
|
|
377
|
+
>
|
|
378
|
+
<SelectTrigger>
|
|
379
|
+
<SelectValue placeholder="Select mode" />
|
|
380
|
+
</SelectTrigger>
|
|
381
|
+
<SelectContent>
|
|
382
|
+
<SelectItem value="aggressive">Aggressive (Maximize performance)</SelectItem>
|
|
383
|
+
<SelectItem value="balanced">Balanced (Performance + stability)</SelectItem>
|
|
384
|
+
<SelectItem value="conservative">Conservative (Minimal changes)</SelectItem>
|
|
385
|
+
</SelectContent>
|
|
386
|
+
</Select>
|
|
387
|
+
</div>
|
|
388
|
+
<div className="space-y-2">
|
|
389
|
+
<Label htmlFor="reoptimize-frequency">Re-optimization Frequency</Label>
|
|
390
|
+
<Select
|
|
391
|
+
defaultValue="weekly"
|
|
392
|
+
options={[
|
|
393
|
+
{ value: "never", label: "Never" },
|
|
394
|
+
{ value: "daily", label: "Daily" },
|
|
395
|
+
{ value: "weekly", label: "Weekly" },
|
|
396
|
+
{ value: "monthly", label: "Monthly" },
|
|
397
|
+
]}
|
|
398
|
+
>
|
|
399
|
+
<SelectTrigger>
|
|
400
|
+
<SelectValue placeholder="Select frequency" />
|
|
401
|
+
</SelectTrigger>
|
|
402
|
+
<SelectContent>
|
|
403
|
+
<SelectItem value="never">Never (Manual only)</SelectItem>
|
|
404
|
+
<SelectItem value="daily">Daily</SelectItem>
|
|
405
|
+
<SelectItem value="weekly">Weekly</SelectItem>
|
|
406
|
+
<SelectItem value="monthly">Monthly</SelectItem>
|
|
407
|
+
</SelectContent>
|
|
408
|
+
</Select>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
<div className="flex items-center justify-between">
|
|
412
|
+
<div className="space-y-0.5">
|
|
413
|
+
<Label>Auto-Optimize New Line Items</Label>
|
|
414
|
+
<p className="text-sm text-muted-foreground">
|
|
415
|
+
Automatically apply AI recommendations to new line items
|
|
416
|
+
</p>
|
|
417
|
+
</div>
|
|
418
|
+
<Switch defaultChecked />
|
|
419
|
+
</div>
|
|
420
|
+
<Separator />
|
|
421
|
+
<div className="flex items-center justify-between">
|
|
422
|
+
<div className="space-y-0.5">
|
|
423
|
+
<Label>Enable A/B Testing</Label>
|
|
424
|
+
<p className="text-sm text-muted-foreground">
|
|
425
|
+
Allow AI to run A/B tests on inventory selection
|
|
426
|
+
</p>
|
|
427
|
+
</div>
|
|
428
|
+
<Switch />
|
|
429
|
+
</div>
|
|
430
|
+
<Separator />
|
|
431
|
+
<div className="flex items-center justify-between">
|
|
432
|
+
<div className="space-y-0.5">
|
|
433
|
+
<Label>Show Optimization Insights</Label>
|
|
434
|
+
<p className="text-sm text-muted-foreground">
|
|
435
|
+
Display AI reasoning and recommendations in the UI
|
|
436
|
+
</p>
|
|
437
|
+
</div>
|
|
438
|
+
<Switch defaultChecked />
|
|
439
|
+
</div>
|
|
440
|
+
</CardContent>
|
|
441
|
+
</Card>
|
|
442
|
+
|
|
443
|
+
<Card>
|
|
444
|
+
<CardHeader>
|
|
445
|
+
<CardTitle className="flex items-center gap-2">
|
|
446
|
+
<Sliders className="h-5 w-5" />
|
|
447
|
+
Recommendation Weights
|
|
448
|
+
</CardTitle>
|
|
449
|
+
<CardDescription>Adjust the importance of each factor in AI recommendations</CardDescription>
|
|
450
|
+
</CardHeader>
|
|
451
|
+
<CardContent className="pt-0 space-y-4">
|
|
452
|
+
<p className="text-sm text-muted-foreground">
|
|
453
|
+
Configure how the 8-factor scoring system weights each component. Values should sum to 100%.
|
|
454
|
+
</p>
|
|
455
|
+
<div className="grid gap-6 sm:grid-cols-2">
|
|
456
|
+
<div className="space-y-3">
|
|
457
|
+
<div className="flex items-center justify-between">
|
|
458
|
+
<Label htmlFor="weight-measure-fit">Measure Fit</Label>
|
|
459
|
+
<span className="text-sm text-muted-foreground">{weights.measureFit}%</span>
|
|
460
|
+
</div>
|
|
461
|
+
<Slider value={[weights.measureFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('measureFit', v)} />
|
|
462
|
+
</div>
|
|
463
|
+
<div className="space-y-3">
|
|
464
|
+
<div className="flex items-center justify-between">
|
|
465
|
+
<Label htmlFor="weight-geo-fit">Geo Fit</Label>
|
|
466
|
+
<span className="text-sm text-muted-foreground">{weights.geoFit}%</span>
|
|
467
|
+
</div>
|
|
468
|
+
<Slider value={[weights.geoFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('geoFit', v)} />
|
|
469
|
+
</div>
|
|
470
|
+
<div className="space-y-3">
|
|
471
|
+
<div className="flex items-center justify-between">
|
|
472
|
+
<Label htmlFor="weight-availability">Availability</Label>
|
|
473
|
+
<span className="text-sm text-muted-foreground">{weights.availability}%</span>
|
|
474
|
+
</div>
|
|
475
|
+
<Slider value={[weights.availability]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('availability', v)} />
|
|
476
|
+
</div>
|
|
477
|
+
<div className="space-y-3">
|
|
478
|
+
<div className="flex items-center justify-between">
|
|
479
|
+
<Label htmlFor="weight-budget-fit">Budget Fit</Label>
|
|
480
|
+
<span className="text-sm text-muted-foreground">{weights.budgetFit}%</span>
|
|
481
|
+
</div>
|
|
482
|
+
<Slider value={[weights.budgetFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('budgetFit', v)} />
|
|
483
|
+
</div>
|
|
484
|
+
<div className="space-y-3">
|
|
485
|
+
<div className="flex items-center justify-between">
|
|
486
|
+
<Label htmlFor="weight-audience-fit">Audience Fit</Label>
|
|
487
|
+
<span className="text-sm text-muted-foreground">{weights.audienceFit}%</span>
|
|
488
|
+
</div>
|
|
489
|
+
<Slider value={[weights.audienceFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('audienceFit', v)} />
|
|
490
|
+
</div>
|
|
491
|
+
<div className="space-y-3">
|
|
492
|
+
<div className="flex items-center justify-between">
|
|
493
|
+
<Label htmlFor="weight-brand-fit">Brand Fit</Label>
|
|
494
|
+
<span className="text-sm text-muted-foreground">{weights.brandFit}%</span>
|
|
495
|
+
</div>
|
|
496
|
+
<Slider value={[weights.brandFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('brandFit', v)} />
|
|
497
|
+
</div>
|
|
498
|
+
<div className="space-y-3">
|
|
499
|
+
<div className="flex items-center justify-between">
|
|
500
|
+
<Label htmlFor="weight-quality-fit">Quality Fit</Label>
|
|
501
|
+
<span className="text-sm text-muted-foreground">{weights.qualityFit}%</span>
|
|
502
|
+
</div>
|
|
503
|
+
<Slider value={[weights.qualityFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('qualityFit', v)} />
|
|
504
|
+
</div>
|
|
505
|
+
<div className="space-y-3">
|
|
506
|
+
<div className="flex items-center justify-between">
|
|
507
|
+
<Label htmlFor="weight-time-fit">Time Fit</Label>
|
|
508
|
+
<span className="text-sm text-muted-foreground">{weights.timeFit}%</span>
|
|
509
|
+
</div>
|
|
510
|
+
<Slider value={[weights.timeFit]} min={0} max={30} step={1} onValueChange={(v) => updateWeight('timeFit', v)} />
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
<Button
|
|
514
|
+
variant="outline"
|
|
515
|
+
size="sm"
|
|
516
|
+
className="mt-2"
|
|
517
|
+
onClick={() => setWeights({
|
|
518
|
+
measureFit: 15, geoFit: 15, availability: 15, budgetFit: 10,
|
|
519
|
+
audienceFit: 15, brandFit: 10, qualityFit: 10, timeFit: 10,
|
|
520
|
+
})}
|
|
521
|
+
>
|
|
522
|
+
Reset to Defaults
|
|
523
|
+
</Button>
|
|
524
|
+
</CardContent>
|
|
525
|
+
</Card>
|
|
526
|
+
|
|
527
|
+
<Card>
|
|
528
|
+
<CardHeader>
|
|
529
|
+
<CardTitle className="flex items-center gap-2">
|
|
530
|
+
<Workflow className="h-5 w-5" />
|
|
531
|
+
Workflow Settings
|
|
532
|
+
</CardTitle>
|
|
533
|
+
<CardDescription>Configure approval workflows and automation</CardDescription>
|
|
534
|
+
</CardHeader>
|
|
535
|
+
<CardContent className="pt-0 space-y-4">
|
|
536
|
+
<div className="flex items-center justify-between">
|
|
537
|
+
<div className="space-y-0.5">
|
|
538
|
+
<Label>Require Creative Approval</Label>
|
|
539
|
+
<p className="text-sm text-muted-foreground">
|
|
540
|
+
All creatives must be approved before going live
|
|
541
|
+
</p>
|
|
542
|
+
</div>
|
|
543
|
+
<Switch defaultChecked />
|
|
544
|
+
</div>
|
|
545
|
+
<Separator />
|
|
546
|
+
<div className="flex items-center justify-between">
|
|
547
|
+
<div className="space-y-0.5">
|
|
548
|
+
<Label>Two-Tier Creative Approval</Label>
|
|
549
|
+
<p className="text-sm text-muted-foreground">
|
|
550
|
+
Enable Tier 2 (Media Owner) approval after Tier 1 (Content Hub)
|
|
551
|
+
</p>
|
|
552
|
+
</div>
|
|
553
|
+
<Switch defaultChecked />
|
|
554
|
+
</div>
|
|
555
|
+
<Separator />
|
|
556
|
+
<div className="flex items-center justify-between">
|
|
557
|
+
<div className="space-y-0.5">
|
|
558
|
+
<Label>Auto-Accept Deals</Label>
|
|
559
|
+
<p className="text-sm text-muted-foreground">
|
|
560
|
+
Automatically accept deals from trusted partners
|
|
561
|
+
</p>
|
|
562
|
+
</div>
|
|
563
|
+
<Switch />
|
|
564
|
+
</div>
|
|
565
|
+
<Separator />
|
|
566
|
+
<div className="flex items-center justify-between">
|
|
567
|
+
<div className="space-y-0.5">
|
|
568
|
+
<Label>Deal Locking</Label>
|
|
569
|
+
<p className="text-sm text-muted-foreground">
|
|
570
|
+
Lock deals after acceptance to prevent modifications
|
|
571
|
+
</p>
|
|
572
|
+
</div>
|
|
573
|
+
<Switch defaultChecked />
|
|
574
|
+
</div>
|
|
575
|
+
</CardContent>
|
|
576
|
+
</Card>
|
|
577
|
+
|
|
578
|
+
<Card>
|
|
579
|
+
<CardHeader>
|
|
580
|
+
<CardTitle className="flex items-center gap-2">
|
|
581
|
+
<Languages className="h-5 w-5" />
|
|
582
|
+
Terminology
|
|
583
|
+
</CardTitle>
|
|
584
|
+
<CardDescription>Customize labels and terminology used throughout the platform</CardDescription>
|
|
585
|
+
</CardHeader>
|
|
586
|
+
<CardContent className="pt-0 space-y-4">
|
|
587
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
588
|
+
<div className="space-y-2">
|
|
589
|
+
<Label htmlFor="term-deal">Deal</Label>
|
|
590
|
+
<Input id="term-deal" defaultValue="Deal" />
|
|
591
|
+
</div>
|
|
592
|
+
<div className="space-y-2">
|
|
593
|
+
<Label htmlFor="term-line-item">Line Item</Label>
|
|
594
|
+
<Input id="term-line-item" defaultValue="Line Item" />
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
597
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
598
|
+
<div className="space-y-2">
|
|
599
|
+
<Label htmlFor="term-creative">Creative</Label>
|
|
600
|
+
<Input id="term-creative" defaultValue="Creative" />
|
|
601
|
+
</div>
|
|
602
|
+
<div className="space-y-2">
|
|
603
|
+
<Label htmlFor="term-inventory">Inventory</Label>
|
|
604
|
+
<Input id="term-inventory" defaultValue="Inventory" />
|
|
605
|
+
</div>
|
|
606
|
+
</div>
|
|
607
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
608
|
+
<div className="space-y-2">
|
|
609
|
+
<Label htmlFor="term-advertiser">Advertiser</Label>
|
|
610
|
+
<Input id="term-advertiser" defaultValue="Advertiser" />
|
|
611
|
+
</div>
|
|
612
|
+
<div className="space-y-2">
|
|
613
|
+
<Label htmlFor="term-campaign">Campaign</Label>
|
|
614
|
+
<Input id="term-campaign" defaultValue="Campaign" />
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
</CardContent>
|
|
618
|
+
</Card>
|
|
619
|
+
|
|
620
|
+
<Card>
|
|
621
|
+
<CardHeader>
|
|
622
|
+
<CardTitle className="flex items-center gap-2">
|
|
623
|
+
<Palette className="h-5 w-5" />
|
|
624
|
+
Themes & Branding
|
|
625
|
+
</CardTitle>
|
|
626
|
+
<CardDescription>Customize the look and feel of your platform</CardDescription>
|
|
627
|
+
</CardHeader>
|
|
628
|
+
<CardContent className="pt-0 space-y-4">
|
|
629
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
630
|
+
<div className="space-y-2">
|
|
631
|
+
<Label htmlFor="theme-mode">Theme Mode</Label>
|
|
632
|
+
<Select
|
|
633
|
+
defaultValue="light"
|
|
634
|
+
options={[
|
|
635
|
+
{ value: "light", label: "Light" },
|
|
636
|
+
{ value: "dark", label: "Dark" },
|
|
637
|
+
{ value: "system", label: "System" },
|
|
638
|
+
]}
|
|
639
|
+
>
|
|
640
|
+
<SelectTrigger>
|
|
641
|
+
<SelectValue placeholder="Select theme" />
|
|
642
|
+
</SelectTrigger>
|
|
643
|
+
<SelectContent>
|
|
644
|
+
<SelectItem value="light">Light</SelectItem>
|
|
645
|
+
<SelectItem value="dark">Dark</SelectItem>
|
|
646
|
+
<SelectItem value="system">System</SelectItem>
|
|
647
|
+
</SelectContent>
|
|
648
|
+
</Select>
|
|
649
|
+
</div>
|
|
650
|
+
<div className="space-y-2">
|
|
651
|
+
<Label htmlFor="primary-color">Primary Color</Label>
|
|
652
|
+
<div className="flex gap-2">
|
|
653
|
+
<Input id="primary-color" type="color" defaultValue="#3B82F6" className="w-14 h-9 p-1" />
|
|
654
|
+
<Input defaultValue="#3B82F6" className="flex-1 font-mono" readOnly />
|
|
655
|
+
</div>
|
|
656
|
+
</div>
|
|
657
|
+
</div>
|
|
658
|
+
<div className="space-y-2">
|
|
659
|
+
<Label htmlFor="logo-url">Logo URL</Label>
|
|
660
|
+
<Input id="logo-url" placeholder="https://example.com/logo.png" />
|
|
661
|
+
</div>
|
|
662
|
+
<div className="flex items-center justify-between">
|
|
663
|
+
<div className="space-y-0.5">
|
|
664
|
+
<Label>Compact Mode</Label>
|
|
665
|
+
<p className="text-sm text-muted-foreground">
|
|
666
|
+
Use a more compact UI with smaller spacing
|
|
667
|
+
</p>
|
|
668
|
+
</div>
|
|
669
|
+
<Switch />
|
|
670
|
+
</div>
|
|
671
|
+
</CardContent>
|
|
672
|
+
</Card>
|
|
673
|
+
|
|
674
|
+
<Card>
|
|
675
|
+
<CardHeader>
|
|
676
|
+
<CardTitle className="flex items-center gap-2">
|
|
677
|
+
<ListFilter className="h-5 w-5" />
|
|
678
|
+
Inventory Whitelisting
|
|
679
|
+
</CardTitle>
|
|
680
|
+
<CardDescription>Control which inventory is available for deals</CardDescription>
|
|
681
|
+
</CardHeader>
|
|
682
|
+
<CardContent className="pt-0 space-y-4">
|
|
683
|
+
<div className="flex items-center justify-between">
|
|
684
|
+
<div className="space-y-0.5">
|
|
685
|
+
<Label>Enable Inventory Whitelisting</Label>
|
|
686
|
+
<p className="text-sm text-muted-foreground">
|
|
687
|
+
Only show whitelisted inventory to advertisers and agencies
|
|
688
|
+
</p>
|
|
689
|
+
</div>
|
|
690
|
+
<Switch />
|
|
691
|
+
</div>
|
|
692
|
+
<Separator />
|
|
693
|
+
<div className="space-y-2">
|
|
694
|
+
<Label htmlFor="whitelist-ids">Whitelisted Inventory IDs</Label>
|
|
695
|
+
<Textarea
|
|
696
|
+
id="whitelist-ids"
|
|
697
|
+
placeholder="Enter inventory IDs separated by commas or new lines"
|
|
698
|
+
className="min-h-[100px] font-mono text-sm"
|
|
699
|
+
/>
|
|
700
|
+
<p className="text-xs text-muted-foreground">
|
|
701
|
+
Leave empty to allow all inventory. Enter specific IDs to restrict availability.
|
|
702
|
+
</p>
|
|
703
|
+
</div>
|
|
704
|
+
<div className="flex items-center justify-between">
|
|
705
|
+
<div className="space-y-0.5">
|
|
706
|
+
<Label>Exclude Adult Content Venues</Label>
|
|
707
|
+
<p className="text-sm text-muted-foreground">
|
|
708
|
+
Automatically exclude venues with adult content classification
|
|
709
|
+
</p>
|
|
710
|
+
</div>
|
|
711
|
+
<Switch defaultChecked />
|
|
712
|
+
</div>
|
|
713
|
+
</CardContent>
|
|
714
|
+
</Card>
|
|
715
|
+
|
|
716
|
+
<Card>
|
|
717
|
+
<CardHeader>
|
|
718
|
+
<CardTitle className="flex items-center gap-2">
|
|
719
|
+
<Globe className="h-5 w-5" />
|
|
720
|
+
API Settings
|
|
721
|
+
</CardTitle>
|
|
722
|
+
<CardDescription>Configure API access and rate limits</CardDescription>
|
|
723
|
+
</CardHeader>
|
|
724
|
+
<CardContent className="pt-0 space-y-4">
|
|
725
|
+
<div className="space-y-2">
|
|
726
|
+
<Label>API Endpoint</Label>
|
|
727
|
+
<div className="flex items-center gap-2">
|
|
728
|
+
<Input
|
|
729
|
+
value="https://api.influence.io/v1"
|
|
730
|
+
readOnly
|
|
731
|
+
className="font-mono text-sm"
|
|
732
|
+
/>
|
|
733
|
+
<Button variant="outline" size="sm">Copy</Button>
|
|
734
|
+
</div>
|
|
735
|
+
</div>
|
|
736
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
737
|
+
<div className="space-y-2">
|
|
738
|
+
<Label htmlFor="rate-limit">Rate Limit (requests/min)</Label>
|
|
739
|
+
<Input id="rate-limit" type="number" defaultValue="1000" />
|
|
740
|
+
</div>
|
|
741
|
+
<div className="space-y-2">
|
|
742
|
+
<Label htmlFor="timeout">Request Timeout (ms)</Label>
|
|
743
|
+
<Input id="timeout" type="number" defaultValue="5000" />
|
|
744
|
+
</div>
|
|
745
|
+
</div>
|
|
746
|
+
</CardContent>
|
|
747
|
+
</Card>
|
|
748
|
+
|
|
749
|
+
<div className="flex justify-end pb-6">
|
|
750
|
+
<Button onClick={handleSave}>
|
|
751
|
+
<Save className="h-4 w-4 mr-2" />
|
|
752
|
+
Save Changes
|
|
753
|
+
</Button>
|
|
754
|
+
</div>
|
|
755
|
+
|
|
756
|
+
</div>
|
|
757
|
+
</div>
|
|
758
|
+
</div>
|
|
759
|
+
);
|
|
760
|
+
}
|