diff --git a/app/(protected)/admin/records/loading.tsx b/app/(protected)/admin/records/loading.tsx
index 229da62..4cb1393 100644
--- a/app/(protected)/admin/records/loading.tsx
+++ b/app/(protected)/admin/records/loading.tsx
@@ -8,7 +8,12 @@ export default function DashboardRecordsLoading() {
heading="Manage DNS Records"
text="List and manage records"
/>
-
+
+
+
+
+
+
>
);
diff --git a/app/(protected)/admin/records/page.tsx b/app/(protected)/admin/records/page.tsx
index e9a61d3..21ee1ab 100644
--- a/app/(protected)/admin/records/page.tsx
+++ b/app/(protected)/admin/records/page.tsx
@@ -5,6 +5,7 @@ import { constructMetadata } from "@/lib/utils";
import { DashboardHeader } from "@/components/dashboard/header";
import UserRecordsList from "../../dashboard/records/record-list";
+import UserRecordStatus from "../../dashboard/records/record-statu";
export const metadata = constructMetadata({
title: "DNS Records",
@@ -24,6 +25,16 @@ export default async function DashboardPage() {
link="/docs/dns-records"
linkText="DNS records"
/>
+
-
+
+
+
+
+
+
>
);
diff --git a/app/(protected)/dashboard/records/page.tsx b/app/(protected)/dashboard/records/page.tsx
index 4854f78..b250cc1 100644
--- a/app/(protected)/dashboard/records/page.tsx
+++ b/app/(protected)/dashboard/records/page.tsx
@@ -5,6 +5,7 @@ import { constructMetadata } from "@/lib/utils";
import { DashboardHeader } from "@/components/dashboard/header";
import UserRecordsList from "./record-list";
+import UserRecordStatus from "./record-statu";
export const metadata = constructMetadata({
title: "DNS Records",
@@ -24,6 +25,16 @@ export default async function DashboardPage() {
link="/docs/dns-records"
linkText="DNS records"
/>
+
;
+ action: string;
+}
+
+export default function UserRecordStatus({ action }: RecordStatusProps) {
+ const { data, isLoading, error } = useSWR>(
+ `${action}/status`,
+ fetcher,
+ );
+
+ if (isLoading || error)
+ return (
+
+
+
+
+
+
+ );
+ return (
+ data && (
+
+
+
+
+
+
+ )
+ );
+}
+
+export function StatuInfoCard({
+ title,
+ total,
+ monthTotal,
+}: {
+ title: string;
+ total?: number;
+ monthTotal: number;
+}) {
+ const t = useTranslations("Components");
+
+ const statusConfig = {
+ Active: {
+ color: "bg-green-500",
+ textColor: "text-green-500",
+ gradient: "from-green-400 to-green-600",
+ shadow: "shadow-green-500/25",
+ },
+ Inactive: {
+ color: "bg-gray-700",
+ textColor: "text-gray-700",
+ gradient: "from-gray-400 to-gray-600",
+ shadow: "shadow-gray-500/25",
+ },
+ Pending: {
+ color: "bg-yellow-500",
+ textColor: "text-yellow-500",
+ gradient: "from-yellow-400 to-yellow-600",
+ shadow: "shadow-yellow-500/25",
+ },
+ Rejected: {
+ color: "bg-red-500",
+ textColor: "text-red-500",
+ gradient: "from-red-400 to-red-600",
+ shadow: "shadow-red-500/25",
+ },
+ };
+
+ const config = statusConfig[title];
+ const percentage = total && total > 0 ? (monthTotal / total) * 100 : 0;
+ const barHeight = Math.max(8, Math.min(100, percentage));
+
+ return (
+
+
+
+
{t(title)}
+
+
+
+ / {nFormatter(total || 0)}
+
+
+
+
+
+
+ {/* 柱状图背景 */}
+
+ {/* 主柱状图 */}
+
+ {/* 光泽效果 */}
+
+ {/* 顶部高光 */}
+ {barHeight > 15 && (
+
+ )}
+
+ {percentage.toFixed(0)}%
+
+
+
+
+
+
+ );
+}
diff --git a/app/api/record/admin/add/route.ts b/app/api/record/admin/add/route.ts
index 96629f9..40ca89e 100644
--- a/app/api/record/admin/add/route.ts
+++ b/app/api/record/admin/add/route.ts
@@ -7,7 +7,6 @@ import {
import { getDomainsByFeature } from "@/lib/dto/domains";
import { getPlanQuota } from "@/lib/dto/plan";
import { checkUserStatus, getUserByEmail } from "@/lib/dto/user";
-import { reservedDomains } from "@/lib/enums";
import { getCurrentUser } from "@/lib/session";
import { generateSecret } from "@/lib/utils";
diff --git a/app/api/record/admin/status/route.ts b/app/api/record/admin/status/route.ts
new file mode 100644
index 0000000..8a74852
--- /dev/null
+++ b/app/api/record/admin/status/route.ts
@@ -0,0 +1,23 @@
+import { getUserRecordStatus } from "@/lib/dto/cloudflare-dns-record";
+import { checkUserStatus } from "@/lib/dto/user";
+import { getCurrentUser } from "@/lib/session";
+
+export async function GET(req: Request) {
+ try {
+ const user = checkUserStatus(await getCurrentUser());
+ if (user instanceof Response) return user;
+ if (user.role !== "ADMIN") {
+ return Response.json("Unauthorized", {
+ status: 401,
+ });
+ }
+
+ const status = await getUserRecordStatus(user.id, "ADMIN");
+
+ return Response.json(status);
+ } catch (error) {
+ return Response.json(error?.statusText || error, {
+ status: error.status || 500,
+ });
+ }
+}
diff --git a/app/api/record/status/route.ts b/app/api/record/status/route.ts
new file mode 100644
index 0000000..6feb4f1
--- /dev/null
+++ b/app/api/record/status/route.ts
@@ -0,0 +1,18 @@
+import { getUserRecordStatus } from "@/lib/dto/cloudflare-dns-record";
+import { checkUserStatus } from "@/lib/dto/user";
+import { getCurrentUser } from "@/lib/session";
+
+export async function GET(req: Request) {
+ try {
+ const user = checkUserStatus(await getCurrentUser());
+ if (user instanceof Response) return user;
+
+ const status = await getUserRecordStatus(user.id, "USER");
+
+ return Response.json(status);
+ } catch (error) {
+ return Response.json(error?.statusText || error, {
+ status: error.status || 500,
+ });
+ }
+}
diff --git a/components/dashboard/status-dot.tsx b/components/dashboard/status-dot.tsx
index 32ae540..2b098c0 100644
--- a/components/dashboard/status-dot.tsx
+++ b/components/dashboard/status-dot.tsx
@@ -1,11 +1,17 @@
import { cn } from "@/lib/utils";
-export default function StatusDot({ status }: { status: number }) {
+export default function StatusDot({
+ status,
+ color = "bg-green-500",
+}: {
+ status: number;
+ color?: string;
+}) {
return (
);
diff --git a/lib/dto/cloudflare-dns-record.ts b/lib/dto/cloudflare-dns-record.ts
index 8811277..eaf6d38 100644
--- a/lib/dto/cloudflare-dns-record.ts
+++ b/lib/dto/cloudflare-dns-record.ts
@@ -229,6 +229,45 @@ export async function getUserRecordCount(
}
}
+export async function getUserRecordStatus(
+ userId: string,
+ role: UserRole = "USER",
+) {
+ const whereCondition = role === "USER" ? { userId } : {};
+
+ const statusCounts = await prisma.userRecord.groupBy({
+ by: ["active"],
+ where: whereCondition,
+ _count: {
+ _all: true,
+ },
+ });
+
+ const total = await prisma.userRecord.count({
+ where: whereCondition,
+ });
+
+ const counts = statusCounts.reduce(
+ (acc, item) => {
+ // if (!item.active) {
+ // acc[0] = item._count._all;
+ // return acc;
+ // }
+ acc[item.active ?? 0] = item._count._all;
+ return acc;
+ },
+ {} as Record,
+ );
+
+ return {
+ total,
+ inactive: counts[0] || 0,
+ active: counts[1] || 0,
+ pending: counts[2] || 0,
+ rejected: counts[3] || 0,
+ };
+}
+
export async function getUserRecordByTypeNameContent(
userId: string,
type: string,
diff --git a/locales/en.json b/locales/en.json
index 5e6fe54..bfa09c2 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -300,7 +300,11 @@
"All the time": "All the time",
"No Visits": "No Visits",
"You don't have any visits yet in": "You don't have any visits yet in",
- "System Settings": "System Settings"
+ "System Settings": "System Settings",
+ "Active": "Active",
+ "Inactive": "Inactive",
+ "Pending": "Pending",
+ "Rejected": "Rejected"
},
"Landing": {
"settings": "Settings",
diff --git a/locales/zh.json b/locales/zh.json
index e77f27a..05e2887 100644
--- a/locales/zh.json
+++ b/locales/zh.json
@@ -300,7 +300,11 @@
"All the time": "所有时间",
"No Visits": "无访问记录",
"You don't have any visits yet in": "您还没有任何访问记录于",
- "System Settings": "系统设置"
+ "System Settings": "系统设置",
+ "Active": "有效解析",
+ "Inactive": "无效解析",
+ "Pending": "审核中",
+ "Rejected": "已拒绝"
},
"Landing": {
"settings": "设置",
diff --git a/public/sw.js.map b/public/sw.js.map
index 27865ba..394873a 100644
--- a/public/sw.js.map
+++ b/public/sw.js.map
@@ -1 +1 @@
-{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/477dc10320d27fdaed55a20fbddecc47/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/a59ec1052fc19feea705f8034ed24f71/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAa,EAEZ,CAAA;EAQDC,CAAI,CAAA,CAAA,CAAA,CAACC,CAAW,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAE,CAAA;AAElBC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAyB,EAAE,CAAA;AAI3BC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAA6B,CAAC,CAAA,CAAA,CAAG,CAAE,CAAA,CAAA,CAAA,CAAA,CAAIC,oBAA+B,CAAC,CAAA;EAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAW,EAAC,CAAW,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAO,EAAE,CAAC,CAAA;GAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAe,EAAE,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;QAAEC,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;QAAEC,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;QAAEC,CAAK,CAAA,CAAA,CAAA,CAAA,CAAA;AAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA;AAAM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAC,CAAK,CAAA,CAAA,CAAA,CAAA,CAAA;EAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAIF,QAAQ,CAAIA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAQ,CAACG,CAAI,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAK,gBAAgB,CAAE,CAAA,CAAA;AAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,OAAO,CAAIC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAQ,CAACJ,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAACK,IAAI,CAAE,CAAA,CAAA;EAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAM,EAAE,CAAG,CAAA,CAAA,CAAA;EAAEC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAU,EAAE,CAAI,CAAA,CAAA,CAAA,CAAA;YAAEC,CAAO,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAER,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAACQ,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA;AAAQ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAC,CAAC,CAAA;EAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAOR,QAAQ,CAAA;EAAC,CAAA,CAAA,CAAA,CAAA,CAAA;KAAG,CAAA;AAAE,CAAA,CAAA,CAAC,CAAC,CAAA,CAAE,CAAK,CAAA,CAAA,CAAA,CAAA,CAAC,CAAA;AACxWL,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAA6B,CAAC,CAAA,CAAA,CAAA,CAAA,CAAK,CAAE,CAAA,CAAA,CAAA,CAAA,CAAIc,mBAA8B,CAAC,CAAA;EAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAW,EAAC,CAAK,CAAA,CAAA,CAAA,CAAA,CAAA;EAAEZ,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAO,EAAE,CAAA,CAAA;EAAG,CAAC,CAAC,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAK,CAAC,CAAA;;"}
\ No newline at end of file