diff --git a/admin/src/App.tsx b/admin/src/App.tsx index 7fc6b99b..4b5e9482 100644 --- a/admin/src/App.tsx +++ b/admin/src/App.tsx @@ -375,10 +375,10 @@ export default function App() { } /> } /> } /> - } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> } /> @@ -807,7 +807,9 @@ export default function App() { path="scheduling/calendar-views/:id" element={ - + + + } /> @@ -815,7 +817,9 @@ export default function App() { path="scheduling/calendar" element={ - + + + } /> diff --git a/admin/src/components/AppLayout.tsx b/admin/src/components/AppLayout.tsx index 06a58bad..37176b2e 100644 --- a/admin/src/components/AppLayout.tsx +++ b/admin/src/components/AppLayout.tsx @@ -309,6 +309,7 @@ function buildMenuItems(settings: import('@/types/api').SiteSettings | null, use { key: '/app/payments/donation-pages', icon: , label: 'Donation Pages' }, { key: '/app/payments/donations', icon: , label: 'Donation Orders' }, { key: '/app/payments/ads', icon: , label: 'Gallery Ads' }, + { key: '/app/payments/ads/analytics', icon: , label: 'Ad Analytics' }, { key: '/app/payments/settings', icon: , label: 'Settings' }, ], }); diff --git a/admin/src/pages/AdminCalendarPage.tsx b/admin/src/pages/AdminCalendarPage.tsx index 47c4bf7f..6ef0f186 100644 --- a/admin/src/pages/AdminCalendarPage.tsx +++ b/admin/src/pages/AdminCalendarPage.tsx @@ -17,14 +17,7 @@ import dayjs from 'dayjs'; import { api } from '@/lib/api'; import type { AdminCalendarView } from '@/types/api'; import type { AppOutletContext } from '@/components/AppLayout'; - -const ROLE_OPTIONS = [ - { label: 'Super Admin', value: 'SUPER_ADMIN' }, - { label: 'Influence Admin', value: 'INFLUENCE_ADMIN' }, - { label: 'Map Admin', value: 'MAP_ADMIN' }, - { label: 'User', value: 'USER' }, - { label: 'Temp', value: 'TEMP' }, -]; +import { ROLE_COLORS, ROLE_OPTIONS } from '@/utils/role-constants'; const LAYER_TYPE_OPTIONS = [ { label: 'Shifts', value: 'SHIFTS' }, @@ -33,14 +26,6 @@ const LAYER_TYPE_OPTIONS = [ { label: 'Public Events', value: 'PUBLIC_EVENTS' }, ]; -const ROLE_COLORS: Record = { - SUPER_ADMIN: 'red', - INFLUENCE_ADMIN: 'blue', - MAP_ADMIN: 'green', - USER: 'default', - TEMP: 'orange', -}; - export default function AdminCalendarPage() { const navigate = useNavigate(); const { setPageHeader } = useOutletContext(); diff --git a/admin/src/pages/AdminCalendarViewPage.tsx b/admin/src/pages/AdminCalendarViewPage.tsx index 5d98caaf..361fca69 100644 --- a/admin/src/pages/AdminCalendarViewPage.tsx +++ b/admin/src/pages/AdminCalendarViewPage.tsx @@ -29,17 +29,10 @@ import type { AdminCalendarUser, AdminCalendarItem, } from '@/types/api'; +import { ROLE_COLORS } from '@/utils/role-constants'; const { Title, Text } = Typography; -const ROLE_COLORS: Record = { - SUPER_ADMIN: 'red', - INFLUENCE_ADMIN: 'blue', - MAP_ADMIN: 'green', - USER: 'default', - TEMP: 'orange', -}; - export default function AdminCalendarViewPage() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); diff --git a/admin/src/pages/SchedulingCalendarPage.tsx b/admin/src/pages/SchedulingCalendarPage.tsx index 5e128b01..23ad5506 100644 --- a/admin/src/pages/SchedulingCalendarPage.tsx +++ b/admin/src/pages/SchedulingCalendarPage.tsx @@ -24,20 +24,13 @@ import UnifiedCalendar from '@/components/calendar/UnifiedCalendar'; import { api } from '@/lib/api'; import type { UnifiedCalendarItem, AdminCalendarView } from '@/types/api'; import { useNavigate } from 'react-router-dom'; +import { ROLE_COLORS, ROLE_OPTIONS } from '@/utils/role-constants'; const { Title, Text } = Typography; const VIEWS_PANEL_WIDTH = 480; const FORM_PANEL_WIDTH = 380; -const ROLE_OPTIONS = [ - { label: 'Super Admin', value: 'SUPER_ADMIN' }, - { label: 'Influence Admin', value: 'INFLUENCE_ADMIN' }, - { label: 'Map Admin', value: 'MAP_ADMIN' }, - { label: 'User', value: 'USER' }, - { label: 'Temp', value: 'TEMP' }, -]; - const LAYER_TYPE_OPTIONS = [ { label: 'Shifts', value: 'SHIFTS' }, { label: 'Tickets', value: 'TICKETS' }, @@ -45,14 +38,6 @@ const LAYER_TYPE_OPTIONS = [ { label: 'Public Events', value: 'PUBLIC_EVENTS' }, ]; -const ROLE_COLORS: Record = { - SUPER_ADMIN: 'red', - INFLUENCE_ADMIN: 'blue', - MAP_ADMIN: 'green', - USER: 'default', - TEMP: 'orange', -}; - export default function SchedulingCalendarPage() { const navigate = useNavigate(); const addEventRef = useRef<(() => void) | null>(null); diff --git a/admin/src/pages/ShiftsPage.tsx b/admin/src/pages/ShiftsPage.tsx index c278622d..c752aa58 100644 --- a/admin/src/pages/ShiftsPage.tsx +++ b/admin/src/pages/ShiftsPage.tsx @@ -121,6 +121,7 @@ export default function ShiftsPage() { const [activeTab, setActiveTab] = useState<'table' | 'calendar'>('table'); const [editModeModalOpen, setEditModeModalOpen] = useState(false); const [editingSeriesShift, setEditingSeriesShift] = useState(null); + const [seriesShiftCount, setSeriesShiftCount] = useState(0); const [calendarData, setCalendarData] = useState({}); const [calendarLoading, setCalendarLoading] = useState(false); const [currentMonth] = useState(dayjs()); @@ -355,6 +356,12 @@ export default function ShiftsPage() { // Part of a series - show edit mode modal setEditingSeriesShift(shift); setEditModeModalOpen(true); + // Fetch series shift count + if (shift.seriesId) { + api.get(`/api/map/shifts/series/${shift.seriesId}/count`) + .then((res) => setSeriesShiftCount(res.data.count ?? 0)) + .catch(() => setSeriesShiftCount(0)); + } } else { // Regular shift or exception - edit normally openEdit(shift); @@ -1207,7 +1214,7 @@ export default function ShiftsPage() { }} onConfirm={handleEditMode} shiftDate={editingSeriesShift?.date || ''} - shiftsCount={0} // TODO: fetch series shifts count + shiftsCount={seriesShiftCount} /> ); diff --git a/admin/src/pages/social/SocialGraphPage.tsx b/admin/src/pages/social/SocialGraphPage.tsx index 0981b1b0..f850ca1c 100644 --- a/admin/src/pages/social/SocialGraphPage.tsx +++ b/admin/src/pages/social/SocialGraphPage.tsx @@ -14,25 +14,10 @@ import { ReactFlowProvider } from '@xyflow/react'; import SocialNetworkGraph, { type GraphData } from '@/components/social/SocialNetworkGraph'; import { api } from '@/lib/api'; import type { AppOutletContext } from '@/types/api'; +import { ROLE_COLORS, ROLE_FILTER_OPTIONS } from '@/utils/role-constants'; const { Text, Title } = Typography; -const ROLE_COLORS: Record = { - SUPER_ADMIN: 'red', - INFLUENCE_ADMIN: 'blue', - MAP_ADMIN: 'green', - USER: 'default', - TEMP: 'orange', -}; - -const ROLE_OPTIONS = [ - { label: 'All Roles', value: '' }, - { label: 'Super Admin', value: 'SUPER_ADMIN' }, - { label: 'Influence Admin', value: 'INFLUENCE_ADMIN' }, - { label: 'Map Admin', value: 'MAP_ADMIN' }, - { label: 'User', value: 'USER' }, -]; - type LayoutMode = 'force' | 'radial'; interface SelectedUser { @@ -145,7 +130,7 @@ function GraphPageInner() {