From 2b05bc1f5f228382c4c9fec74d19f81f71697a20 Mon Sep 17 00:00:00 2001 From: Pallavi Kumari Date: Mon, 20 Oct 2025 01:39:39 +0530 Subject: [PATCH] ui and layout fix --- messages/en-US.json | 4 +- server/db/pg/schema/schema.ts | 1 + server/db/sqlite/schema/schema.ts | 1 + .../[domainId]/DomainSettingsLayout.tsx | 112 ------------------ .../settings/domains/[domainId]/layout.tsx | 20 ++-- .../settings/domains/[domainId]/page.tsx | 108 ++++++++++++++++- src/components/DNSRecordTable.tsx | 8 +- src/components/DNSRecordsDataTable.tsx | 8 +- src/components/DomainInfoCard.tsx | 33 ++++-- src/contexts/domainContext.ts | 12 +- src/providers/DomainProvider.tsx | 6 +- 11 files changed, 159 insertions(+), 154 deletions(-) delete mode 100644 src/app/[orgId]/settings/domains/[domainId]/DomainSettingsLayout.tsx diff --git a/messages/en-US.json b/messages/en-US.json index 4d382869..d53765cf 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -1904,5 +1904,7 @@ "recordName": "Record Name", "auto": "Auto", "TTL": "TTL", - "howToAddRecords": "How to Add Records" + "howToAddRecords": "How to Add Records", + "dnsRecord": "DNS Records", + "required": "Required" } diff --git a/server/db/pg/schema/schema.ts b/server/db/pg/schema/schema.ts index 0b1192f7..36130d36 100644 --- a/server/db/pg/schema/schema.ts +++ b/server/db/pg/schema/schema.ts @@ -33,6 +33,7 @@ export const dnsRecords = pgTable("dnsRecords", { recordType: varchar("recordType").notNull(), // "NS" | "CNAME" | "A" | "TXT" baseDomain: varchar("baseDomain"), value: varchar("value").notNull(), + verified: boolean("verified").notNull().default(false), }); export const orgs = pgTable("orgs", { diff --git a/server/db/sqlite/schema/schema.ts b/server/db/sqlite/schema/schema.ts index bc1ce81b..d3390c21 100644 --- a/server/db/sqlite/schema/schema.ts +++ b/server/db/sqlite/schema/schema.ts @@ -25,6 +25,7 @@ export const dnsRecords = sqliteTable("dnsRecords", { recordType: text("recordType").notNull(), // "NS" | "CNAME" | "A" | "TXT" baseDomain: text("baseDomain"), value: text("value").notNull(), + verified: integer("verified", { mode: "boolean" }).notNull().default(false), }); diff --git a/src/app/[orgId]/settings/domains/[domainId]/DomainSettingsLayout.tsx b/src/app/[orgId]/settings/domains/[domainId]/DomainSettingsLayout.tsx deleted file mode 100644 index 3b822dc0..00000000 --- a/src/app/[orgId]/settings/domains/[domainId]/DomainSettingsLayout.tsx +++ /dev/null @@ -1,112 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { createApiClient, formatAxiosError } from "@app/lib/api"; -import { useEnvContext } from "@app/hooks/useEnvContext"; -import { toast } from "@app/hooks/useToast"; -import { useRouter } from "next/navigation"; -import { RefreshCw } from "lucide-react"; -import { Button } from "@app/components/ui/button"; -import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; -import DomainInfoCard from "@app/components/DomainInfoCard"; -import DomainProvider from "@app/providers/DomainProvider"; -import { useTranslations } from "next-intl"; - - -interface DomainSettingsLayoutProps { - orgId: string; - domain: any, - children: React.ReactNode; -} - -export default function DomainSettingsLayout({ orgId, domain, children }: DomainSettingsLayoutProps) { - const router = useRouter(); - const api = createApiClient(useEnvContext()); - const [isRefreshing, setIsRefreshing] = useState(false); - const [restartingDomains, setRestartingDomains] = useState>(new Set()); - const t = useTranslations(); - const refreshData = async () => { - setIsRefreshing(true); - try { - await new Promise((resolve) => setTimeout(resolve, 200)); - router.refresh(); - } catch { - toast({ - title: t("error"), - description: t("refreshError"), - variant: "destructive", - }); - } finally { - setIsRefreshing(false); - } - }; - - const restartDomain = async (domainId: string) => { - setRestartingDomains((prev) => new Set(prev).add(domainId)); - try { - await api.post(`/org/${orgId}/domain/${domainId}/restart`); - toast({ - title: t("success"), - description: t("domainRestartedDescription", { - fallback: "Domain verification restarted successfully", - }), - }); - refreshData(); - } catch (e) { - toast({ - title: t("error"), - description: formatAxiosError(e), - variant: "destructive", - }); - } finally { - setRestartingDomains((prev) => { - const newSet = new Set(prev); - newSet.delete(domainId); - return newSet; - }); - } - }; - - const isRestarting = restartingDomains.has(domain.domainId); - - return ( - <> -
- - - -
- - -
- -
- {children} -
- - ); -} diff --git a/src/app/[orgId]/settings/domains/[domainId]/layout.tsx b/src/app/[orgId]/settings/domains/[domainId]/layout.tsx index 7c2c3ca5..d33d666a 100644 --- a/src/app/[orgId]/settings/domains/[domainId]/layout.tsx +++ b/src/app/[orgId]/settings/domains/[domainId]/layout.tsx @@ -3,18 +3,17 @@ import { authCookieHeader } from "@app/lib/api/cookies"; import { internal } from "@app/lib/api"; import { GetDomainResponse } from "@server/routers/domain/getDomain"; import { AxiosResponse } from "axios"; -import { getTranslations } from "next-intl/server"; -import SettingsLayoutClient from "./DomainSettingsLayout"; +import DomainProvider from "@app/providers/DomainProvider"; interface SettingsLayoutProps { children: React.ReactNode; - params: { domainId: string; orgId: string }; + params: Promise<{ domainId: string; orgId: string }>; } export default async function SettingsLayout({ children, params }: SettingsLayoutProps) { - const { domainId, orgId } = params; - + const { domainId, orgId } = await params; let domain = null; + try { const res = await internal.get>( `/org/${orgId}/domain/${domainId}`, @@ -25,14 +24,9 @@ export default async function SettingsLayout({ children, params }: SettingsLayou redirect(`/${orgId}/settings/domains`); } - const t = await getTranslations(); - return ( - + {children} - + ); -} +} \ No newline at end of file diff --git a/src/app/[orgId]/settings/domains/[domainId]/page.tsx b/src/app/[orgId]/settings/domains/[domainId]/page.tsx index 02efa517..3051def0 100644 --- a/src/app/[orgId]/settings/domains/[domainId]/page.tsx +++ b/src/app/[orgId]/settings/domains/[domainId]/page.tsx @@ -1,3 +1,105 @@ -export default function DomainPage() { - return null; -} +"use client"; +import { useState } from "react"; +import { createApiClient, formatAxiosError } from "@app/lib/api"; +import { useEnvContext } from "@app/hooks/useEnvContext"; +import { toast } from "@app/hooks/useToast"; +import { useRouter } from "next/navigation"; +import { RefreshCw } from "lucide-react"; +import { Button } from "@app/components/ui/button"; +import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; +import DomainInfoCard from "@app/components/DomainInfoCard"; +import { useDomain } from "@app/contexts/domainContext"; +import { useTranslations } from "next-intl"; + +export default function DomainSettingsPage() { + const { domain, orgId } = useDomain(); + const router = useRouter(); + const api = createApiClient(useEnvContext()); + const [isRefreshing, setIsRefreshing] = useState(false); + const [restartingDomains, setRestartingDomains] = useState>(new Set()); + const t = useTranslations(); + + const refreshData = async () => { + setIsRefreshing(true); + try { + await new Promise((resolve) => setTimeout(resolve, 200)); + router.refresh(); + } catch { + toast({ + title: t("error"), + description: t("refreshError"), + variant: "destructive", + }); + } finally { + setIsRefreshing(false); + } + }; + + const restartDomain = async (domainId: string) => { + setRestartingDomains((prev) => new Set(prev).add(domainId)); + try { + await api.post(`/org/${orgId}/domain/${domainId}/restart`); + toast({ + title: t("success"), + description: t("domainRestartedDescription", { + fallback: "Domain verification restarted successfully", + }), + }); + refreshData(); + } catch (e) { + toast({ + title: t("error"), + description: formatAxiosError(e), + variant: "destructive", + }); + } finally { + setRestartingDomains((prev) => { + const newSet = new Set(prev); + newSet.delete(domainId); + return newSet; + }); + } + }; + + if (!domain) { + return null; + } + + const isRestarting = restartingDomains.has(domain.domainId); + + return ( + <> +
+ + +
+
+ +
+ + ); +} \ No newline at end of file diff --git a/src/components/DNSRecordTable.tsx b/src/components/DNSRecordTable.tsx index e0760977..393f5c24 100644 --- a/src/components/DNSRecordTable.tsx +++ b/src/components/DNSRecordTable.tsx @@ -1,12 +1,8 @@ "use client"; import { ColumnDef } from "@tanstack/react-table"; -import { Button } from "@app/components/ui/button"; -import { useState } from "react"; import { useTranslations } from "next-intl"; -import { useToast } from "@app/hooks/useToast"; import { Badge } from "@app/components/ui/badge"; -import CopyToClipboard from "@app/components/CopyToClipboard"; import { DNSRecordsDataTable } from "./DNSRecordsDataTable"; export type DNSRecordRow = { @@ -114,7 +110,9 @@ export default function DNSRecordsTable({ records, domainId, isRefreshing }: Pro verified ? ( {t("verified")} ) : ( - {t("unverified")} + + {t("failed", { fallback: "Failed" })} + ) ); } diff --git a/src/components/DNSRecordsDataTable.tsx b/src/components/DNSRecordsDataTable.tsx index 422cf318..b29c67f8 100644 --- a/src/components/DNSRecordsDataTable.tsx +++ b/src/components/DNSRecordsDataTable.tsx @@ -108,9 +108,9 @@ export function DNSRecordsDataTable({
-
-

DNS Records

- Required +
+

{t("dnsRecord")}

+ {t("required")}