+
+ {step !== 'year' ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ Day
+
+
+
+
+ {step === 'year' ? (
+
+ {years.map((year) => (
+
+ ))}
+
+ ) : null}
+
+ {step === 'month' ? (
+
+ {MONTHS.map((label, index) => {
+ const month = index + 1
+ return (
+
+ )
+ })}
+
+ ) : null}
+
+ {step === 'day' ? (
+
+
+ {['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((d) => (
+
+ {d}
+
+ ))}
+
+
+ {Array.from({ length: padStart }, (_, i) => (
+
+ ))}
+ {Array.from({ length: dayCount }, (_, i) => {
+ const day = i + 1
+ const isSelected =
+ selected?.year === draftYear &&
+ selected?.month === draftMonth &&
+ selected?.day === day
+ const isToday =
+ draftYear === today.year &&
+ draftMonth === today.month &&
+ day === today.day
+ return (
+
+ )
+ })}
+
+
+ ) : null}
+
,
+ document.body,
+ )
+ : null
+
return (
-
- {open ? (
-
-
- {step !== 'year' ? (
-
- ) : (
-
- )}
-
-
-
-
- Day
-
-
-
-
- {step === 'year' ? (
-
- {years.map((year) => (
-
- ))}
-
- ) : null}
-
- {step === 'month' ? (
-
- {MONTHS.map((label, index) => {
- const month = index + 1
- return (
-
- )
- })}
-
- ) : null}
-
- {step === 'day' ? (
-
-
- {['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((d) => (
-
- {d}
-
- ))}
-
-
- {Array.from({ length: padStart }, (_, i) => (
-
- ))}
- {Array.from({ length: dayCount }, (_, i) => {
- const day = i + 1
- const isSelected =
- selected?.year === draftYear &&
- selected?.month === draftMonth &&
- selected?.day === day
- const isToday =
- draftYear === today.year &&
- draftMonth === today.month &&
- day === today.day
- return (
-
- )
- })}
-
-
- ) : null}
-
- ) : null}
+ {panel}
)
}
diff --git a/apps/super-admin/src/pages/BusinessesPage.module.css b/apps/super-admin/src/pages/BusinessesPage.module.css
index bc1f701..3a93e4e 100644
--- a/apps/super-admin/src/pages/BusinessesPage.module.css
+++ b/apps/super-admin/src/pages/BusinessesPage.module.css
@@ -608,6 +608,129 @@
font-size: 12px;
}
+.promptsListHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 12px;
+}
+
+.promptsListTitle {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--text-secondary);
+}
+
+.promptsRowActions {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ flex-shrink: 0;
+}
+
+.promptsTextarea {
+ width: 100%;
+ min-height: 200px;
+ padding: var(--field-padding-y) var(--field-padding-x);
+ font-size: var(--field-font-size);
+ font-family: var(--font-ui);
+ line-height: 1.5;
+ color: var(--text-primary);
+ background: rgba(255, 255, 255, 0.65);
+ border: 1px solid rgba(148, 163, 184, 0.35);
+ border-radius: var(--radius-sm);
+ outline: none;
+ resize: vertical;
+ box-sizing: border-box;
+}
+
+.promptsTextarea:focus {
+ border-color: var(--primary);
+ box-shadow: 0 0 0 3px rgba(var(--primary-rgb) / 0.12);
+}
+
+.promptsEmpty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ padding: 28px 16px;
+ border: 1px dashed rgba(148, 163, 184, 0.45);
+ border-radius: var(--radius-sm);
+ color: var(--text-secondary);
+ text-align: center;
+}
+
+.promptsEmpty svg {
+ color: var(--primary);
+}
+
+.promptsEmpty p {
+ margin: 0;
+ font-size: 13px;
+}
+
+.promptsList {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.promptsRow {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 12px;
+ border: 1px solid rgba(148, 163, 184, 0.28);
+ border-radius: var(--radius-sm);
+ background: rgba(255, 255, 255, 0.65);
+}
+
+.promptsRowText {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.promptsRowName {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--text-primary);
+}
+
+.promptsRowPreview {
+ font-size: 12px;
+ color: var(--text-muted);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.promptsAddRow {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ gap: 10px;
+ align-items: end;
+ margin-top: 14px;
+}
+
+.promptsLinkRow {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+}
+
+.promptsLinkRow input {
+ flex: 1;
+ min-width: 0;
+}
+
.domainCell {
display: inline-flex;
align-items: center;
diff --git a/apps/super-admin/src/pages/BusinessesPage.tsx b/apps/super-admin/src/pages/BusinessesPage.tsx
index f6af15e..545382a 100644
--- a/apps/super-admin/src/pages/BusinessesPage.tsx
+++ b/apps/super-admin/src/pages/BusinessesPage.tsx
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
AlertTriangle,
+ Copy,
Database,
FileText,
Globe,
@@ -10,6 +11,7 @@ import {
Plus,
RotateCcw,
Search,
+ Trash2,
UserCog,
} from 'lucide-react'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
@@ -46,6 +48,14 @@ import {
} from '../services/businessService'
import { listBusinessCategories } from '../services/categoryService'
import { listUserTitles, type UserTitleOption } from '../services/userTitleService'
+import {
+ createDomainAiPrompt,
+ deleteDomainAiPrompt,
+ listAiPromptTemplates,
+ listDomainAiPrompts,
+ updateDomainAiPrompt,
+} from '../services/aiPromptService'
+import type { AiPromptTemplate, DomainAiPrompt } from '../types/aiPrompt'
import { Modal } from '../components/Modal'
import { PrimaryColorSwatchControl } from '../components/PrimaryColorSwatchControl'
import { useToast } from '../context/ToastContext'
@@ -315,6 +325,21 @@ export function BusinessesPage() {
const [domainSubmitting, setDomainSubmitting] = useState(false)
const [domainError, setDomainError] = useState('')
+ const [promptsOpen, setPromptsOpen] = useState(false)
+ const [promptsBusiness, setPromptsBusiness] = useState