diff --git a/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx b/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx new file mode 100644 index 00000000..024fc10b --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx @@ -0,0 +1,83 @@ +import { + Button, + Checkbox, + Column, + Form, + FormField, + FormSubmitButton, + Row, + Text, +} from '@umami/react-zen'; +import { useState } from 'react'; +import { useApi, useMessages, useModified } from '@/components/hooks'; +import { SHARE_NAV_ITEMS } from './constants'; + +export interface ShareCreateFormProps { + websiteId: string; + onSave?: () => void; + onClose?: () => void; +} + +export function ShareCreateForm({ websiteId, onSave, onClose }: ShareCreateFormProps) { + const { formatMessage, labels } = useMessages(); + const { post } = useApi(); + const { touch } = useModified(); + const [isPending, setIsPending] = useState(false); + + // Build default values - all enabled by default + const defaultValues: Record = {}; + SHARE_NAV_ITEMS.forEach(section => { + section.items.forEach(item => { + defaultValues[item.id] = true; + }); + }); + + const handleSubmit = async (data: any) => { + setIsPending(true); + try { + const parameters: Record = {}; + SHARE_NAV_ITEMS.forEach(section => { + section.items.forEach(item => { + parameters[item.id] = data[item.id] ?? true; + }); + }); + await post(`/websites/${websiteId}/shares`, { parameters }); + touch('shares'); + onSave?.(); + onClose?.(); + } finally { + setIsPending(false); + } + }; + + return ( +
+ + {SHARE_NAV_ITEMS.map(section => ( + + + {formatMessage((labels as any)[section.section])} + + + {section.items.map(item => ( + + + {formatMessage((labels as any)[item.label])} + + + ))} + + + ))} + + {onClose && ( + + )} + {formatMessage(labels.save)} + + +
+ ); +} diff --git a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx index b1d7d50a..5e8f8a74 100644 --- a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx @@ -1,16 +1,20 @@ import { Button, + Checkbox, Column, Form, + FormField, FormSubmitButton, Label, Loading, Row, + Text, TextField, } from '@umami/react-zen'; import { useEffect, useState } from 'react'; import { useApi, useConfig, useMessages, useModified } from '@/components/hooks'; import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery'; +import { SHARE_NAV_ITEMS } from './constants'; export function ShareEditForm({ shareId, @@ -50,8 +54,15 @@ export function ShareEditForm({ }, [shareId, modified]); const handleSubmit = async (data: any) => { + const parameters: Record = {}; + SHARE_NAV_ITEMS.forEach(section => { + section.items.forEach(item => { + parameters[item.id] = data[item.id] ?? true; + }); + }); + await mutateAsync( - { slug: data.slug, parameters: share?.parameters || {} }, + { slug: share.slug, parameters }, { onSuccess: async () => { toast(formatMessage(messages.saved)); @@ -69,24 +80,42 @@ export function ShareEditForm({ const url = getUrl(share?.slug || ''); + // Build default values from share parameters + const defaultValues: Record = {}; + SHARE_NAV_ITEMS.forEach(section => { + section.items.forEach(item => { + defaultValues[item.id] = share?.parameters?.[item.id] ?? true; + }); + }); + return ( -
- + + + {SHARE_NAV_ITEMS.map(section => ( + + + {formatMessage((labels as any)[section.section])} + + + {section.items.map(item => ( + + {formatMessage((labels as any)[item.label])} + + ))} + + + ))} {onClose && ( )} - {formatMessage(labels.save)} + {formatMessage(labels.save)} diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx index 6ac4a404..7453b402 100644 --- a/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx +++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx @@ -1,6 +1,8 @@ -import { Button, Column, Heading, Row, Text } from '@umami/react-zen'; +import { Column, Heading, Row, Text } from '@umami/react-zen'; import { Plus } from 'lucide-react'; -import { useApi, useMessages, useModified, useWebsiteSharesQuery } from '@/components/hooks'; +import { useMessages, useWebsiteSharesQuery } from '@/components/hooks'; +import { DialogButton } from '@/components/input/DialogButton'; +import { ShareCreateForm } from './ShareCreateForm'; import { SharesTable } from './SharesTable'; export interface WebsiteShareFormProps { @@ -10,13 +12,6 @@ export interface WebsiteShareFormProps { export function WebsiteShareForm({ websiteId }: WebsiteShareFormProps) { const { formatMessage, labels, messages } = useMessages(); const { data, isLoading } = useWebsiteSharesQuery({ websiteId }); - const { post } = useApi(); - const { touch } = useModified(); - - const handleCreate = async () => { - await post(`/websites/${websiteId}/shares`, { parameters: {} }); - touch('shares'); - }; const shares = data?.data || []; const hasShares = shares.length > 0; @@ -25,10 +20,15 @@ export function WebsiteShareForm({ websiteId }: WebsiteShareFormProps) { {formatMessage(labels.share)} - + } + label={formatMessage(labels.add)} + title={formatMessage(labels.share)} + variant="primary" + width="400px" + > + {({ close }) => } + {hasShares ? ( <> diff --git a/src/app/(main)/websites/[websiteId]/settings/constants.ts b/src/app/(main)/websites/[websiteId]/settings/constants.ts new file mode 100644 index 00000000..f4a3df80 --- /dev/null +++ b/src/app/(main)/websites/[websiteId]/settings/constants.ts @@ -0,0 +1,30 @@ +export const SHARE_NAV_ITEMS = [ + { + section: 'traffic', + items: [ + { id: 'overview', label: 'overview' }, + { id: 'events', label: 'events' }, + { id: 'sessions', label: 'sessions' }, + { id: 'realtime', label: 'realtime' }, + { id: 'compare', label: 'compare' }, + { id: 'breakdown', label: 'breakdown' }, + ], + }, + { + section: 'behavior', + items: [ + { id: 'goals', label: 'goals' }, + { id: 'funnels', label: 'funnels' }, + { id: 'journeys', label: 'journeys' }, + { id: 'retention', label: 'retention' }, + ], + }, + { + section: 'growth', + items: [ + { id: 'utm', label: 'utm' }, + { id: 'revenue', label: 'revenue' }, + { id: 'attribution', label: 'attribution' }, + ], + }, +];