From bc451eea16b51f1ab81b6cacf65201886866e1cc Mon Sep 17 00:00:00 2001 From: "web@ppanel" Date: Mon, 29 Dec 2025 05:51:24 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Added=20reset=20and=20pause?= =?UTF-8?q?=20subscription=20functionality,=20and=20updated=20the=20status?= =?UTF-8?q?=20display.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/assets/locales/en-US/user.json | 15 ++++ .../public/assets/locales/zh-CN/user.json | 15 ++++ .../sections/user/user-subscription/index.tsx | 90 +++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/apps/admin/public/assets/locales/en-US/user.json b/apps/admin/public/assets/locales/en-US/user.json index f5a55e7..0127346 100644 --- a/apps/admin/public/assets/locales/en-US/user.json +++ b/apps/admin/public/assets/locales/en-US/user.json @@ -71,6 +71,21 @@ "remove": "Remove", "resetLogs": "Reset Logs", "resetTime": "Reset Time", + "resetToken": "Reset Subscription Address", + "resetTokenDescription": "This will reset the subscription address and regenerate a new token.", + "resetTokenSuccess": "Subscription address reset successfully", + "confirmResetToken": "Confirm Reset Subscription Address", + "stopSubscribe": "Stop Subscription", + "stopSubscribeDescription": "This will stop the subscription temporarily. User will not be able to use it.", + "stopSubscribeSuccess": "Subscription stopped successfully", + "confirmStopSubscribe": "Confirm Stop Subscription", + "status": "Status", + "statusPending": "Pending", + "statusActive": "Active", + "statusFinished": "Finished", + "statusExpired": "Expired", + "statusDeducted": "Deducted", + "statusStopped": "Stopped", "save": "Save", "speedLimit": "Speed Limit", "startTime": "startTime", diff --git a/apps/admin/public/assets/locales/zh-CN/user.json b/apps/admin/public/assets/locales/zh-CN/user.json index 57b7bc8..e4dc3d2 100644 --- a/apps/admin/public/assets/locales/zh-CN/user.json +++ b/apps/admin/public/assets/locales/zh-CN/user.json @@ -71,6 +71,21 @@ "remove": "移除", "resetLogs": "重置日志", "resetTime": "重置时间", + "resetToken": "重置订阅地址", + "resetTokenDescription": "这将重置订阅地址并重新生成新的令牌。", + "resetTokenSuccess": "订阅地址重置成功", + "confirmResetToken": "确认重置订阅地址", + "stopSubscribe": "暂停订阅", + "stopSubscribeDescription": "这将暂时停止订阅。用户将无法使用。", + "stopSubscribeSuccess": "订阅已暂停", + "confirmStopSubscribe": "确认暂停订阅", + "status": "状态", + "statusPending": "待处理", + "statusActive": "活跃", + "statusFinished": "已完成", + "statusExpired": "已过期", + "statusDeducted": "已扣除", + "statusStopped": "已停止", "save": "保存", "speedLimit": "速度限制", "startTime": "开始时间", diff --git a/apps/admin/src/sections/user/user-subscription/index.tsx b/apps/admin/src/sections/user/user-subscription/index.tsx index a279d18..fd90618 100644 --- a/apps/admin/src/sections/user/user-subscription/index.tsx +++ b/apps/admin/src/sections/user/user-subscription/index.tsx @@ -1,4 +1,5 @@ import { Link } from "@tanstack/react-router"; +import { Badge } from "@workspace/ui/components/badge"; import { Button } from "@workspace/ui/components/button"; import { DropdownMenu, @@ -15,6 +16,8 @@ import { createUserSubscribe, deleteUserSubscribe, getUserSubscribe, + resetUserSubscribeToken, + stopUserSubscribe, updateUserSubscribe, } from "@workspace/ui/services/admin/user"; import { useRef, useState } from "react"; @@ -68,6 +71,53 @@ export default function UserSubscription({ userId }: { userId: number }) { > {t("copySubscription", "Copy Subscription")} , + { + await resetUserSubscribeToken({ user_subscribe_id: row.id }); + toast.success( + t( + "resetTokenSuccess", + "Subscription address reset successfully" + ) + ); + ref.current?.refresh(); + }} + title={t("confirmResetToken", "Confirm Reset Subscription Address")} + trigger={ + + } + />, + { + await stopUserSubscribe({ user_subscribe_id: row.id }); + toast.success( + t("stopSubscribeSuccess", "Subscription stopped successfully") + ); + ref.current?.refresh(); + }} + title={t("confirmStopSubscribe", "Confirm Stop Subscription")} + trigger={ + + } + />, row.original.subscribe.name, }, + { + accessorKey: "status", + header: t("status", "Status"), + cell: ({ row }) => { + const status = row.getValue("status") as number; + const statusMap: Record< + number, + { + label: string; + variant: "default" | "secondary" | "destructive" | "outline"; + } + > = { + 0: { label: t("statusPending", "Pending"), variant: "outline" }, + 1: { label: t("statusActive", "Active"), variant: "default" }, + 2: { + label: t("statusFinished", "Finished"), + variant: "secondary", + }, + 3: { + label: t("statusExpired", "Expired"), + variant: "destructive", + }, + 4: { + label: t("statusDeducted", "Deducted"), + variant: "secondary", + }, + 5: { + label: t("statusStopped", "Stopped"), + variant: "destructive", + }, + }; + const statusInfo = statusMap[status] || { + label: "Unknown", + variant: "outline", + }; + return ( + {statusInfo.label} + ); + }, + }, { accessorKey: "upload", header: t("upload", "Upload"),