diff --git a/src/app/(dashboard)/projects/[projectId]/services/page.tsx b/src/app/(dashboard)/projects/[projectId]/services/page.tsx index fdffed8..020f867 100644 --- a/src/app/(dashboard)/projects/[projectId]/services/page.tsx +++ b/src/app/(dashboard)/projects/[projectId]/services/page.tsx @@ -1,5 +1,240 @@ +"use client"; + +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + getAnalyticsConfig, + getEmailConfig, + getFileConfig, +} from "@/lib/settings"; +import { getAllFileProviders } from "@/lib/fileProvider"; +import { useQuery } from "@tanstack/react-query"; +import { ArrowRight } from "lucide-react"; +import Link from "next/link"; +import { useParams } from "next/navigation"; +import { getApiKeysAction } from "@/lib/actions"; +import { + UserType, + useUserSession, +} from "@/components/providers/SessionProvider"; + const ServicesPage = () => { - return <>>; + const { projectId } = useParams<{ projectId: string }>(); + const { user } = useUserSession(); + const isAdmin = user && user.type !== UserType.USER; + + const { data: emailConfig, isLoading: emailLoading } = useQuery({ + queryKey: ["emailConfig", projectId], + queryFn: () => getEmailConfig(projectId), + enabled: !!projectId, + staleTime: 0, + refetchOnMount: "always", + }); + + const { data: fileConfig, isLoading: fileConfigLoading } = useQuery({ + queryKey: ["fileConfig", projectId], + queryFn: () => getFileConfig(projectId), + enabled: !!projectId, + staleTime: 0, + refetchOnMount: "always", + }); + + const { data: analyticsConfig, isLoading: analyticsLoading } = useQuery({ + queryKey: ["analyticsConfig", projectId], + queryFn: () => getAnalyticsConfig(projectId), + enabled: !!projectId, + staleTime: 0, + refetchOnMount: "always", + }); + + const { data: providers, isLoading: providersLoading } = useQuery({ + queryKey: ["fileProvider", projectId], + queryFn: () => getAllFileProviders(projectId), + enabled: !!projectId && !!fileConfig, + staleTime: 0, + refetchOnMount: "always", + }); + + const { data: apiKeyData, isLoading: apiKeysLoading } = useQuery({ + queryKey: ["apiKeyCount", projectId], + queryFn: async () => { + const limit = 100; + let offset = 0; + let count = 0; + + while (true) { + const result = await getApiKeysAction({ + offset, + limit, + }); + + if (!result.success) { + return { count: null, error: result.error }; + } + + const keys = result.keys ?? []; + + count += keys.filter( + (key) => String(key.project) === String(projectId), + ).length; + + if (keys.length < limit) { + break; + } + + offset += limit; + } + + return { count, error: null }; + }, + enabled: !!projectId && isAdmin, + staleTime: 0, + refetchOnMount: "always", + }); + + const apiKeyCount = apiKeyData?.count ?? null; + const apiKeyAccessDenied = !isAdmin || apiKeyData?.error != null; + + const isEmailConfigured = emailConfig !== null; + const isFileConfigured = fileConfig !== null; + const isAnalyticsConfigured = analyticsConfig !== null; + + const hasProvider = (providers?.length ?? 0) > 0; + const hasBucket = (fileConfig?.buckets?.length ?? 0) > 0; + const hasFiles = (fileConfig?.files?.length ?? 0) > 0; + + const services = [ + { + name: "Email", + configured: isEmailConfigured, + loading: emailLoading, + description: + "Configure email to send messages and notifications from your project.", + href: `/projects/${projectId}/services/email`, + }, + { + name: "Files", + configured: isFileConfigured, + loading: fileConfigLoading, + description: + "Configure file storage and manage buckets and uploaded files.", + href: `/projects/${projectId}/services/files`, + }, + { + name: "Analytics", + configured: isAnalyticsConfigured, + loading: analyticsLoading, + description: + "Configure analytics to track user interactions, visits, clicks, and custom events.", + href: `/projects/${projectId}/analytics`, + }, + { + name: "API Keys", + configured: null, + loading: false, + description: + "Create and manage API keys used to authenticate your project.", + href: `/projects/${projectId}/keys`, + adminOnly: true, + }, + ]; + + return ( +
+ {service.description} +
+ {service.name === "API Keys" && isAdmin && ( +