mirror of
https://github.com/coaidev/coai.git
synced 2025-06-02 11:50:23 +09:00
update package
This commit is contained in:
parent
f9aac47b67
commit
0d53961c18
@ -28,7 +28,8 @@ import { Toaster } from "./components/ui/toaster.tsx";
|
||||
import {login, tokenField} from "./conf.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Quota from "./routes/Quota.tsx";
|
||||
import {openDialog} from "./store/quota.ts";
|
||||
import { openDialog as openQuotaDialog } from "./store/quota.ts";
|
||||
import { openDialog as openPackageDialog } from "./store/package.ts";
|
||||
import Package from "./routes/Package.tsx";
|
||||
|
||||
function Settings() {
|
||||
@ -49,7 +50,8 @@ function Settings() {
|
||||
{username}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => dispatch(openDialog())}>{t("quota")}</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => dispatch(openQuotaDialog())}>{t("quota")}</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => dispatch(openPackageDialog())}>{t("pkg.title")}</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem asChild>
|
||||
<Button
|
||||
|
@ -0,0 +1,31 @@
|
||||
.package-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 24px 4px !important;
|
||||
gap: 18px;
|
||||
|
||||
.package {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.package-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 16px;
|
||||
color: hsl(var(--text));
|
||||
user-select: none;
|
||||
|
||||
svg {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
}
|
||||
|
||||
.package-content {
|
||||
font-size: 14px;
|
||||
color: hsl(var(--text-secondary));
|
||||
}
|
||||
}
|
||||
}
|
36
app/src/components/ui/badge.tsx
Normal file
36
app/src/components/ui/badge.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "./lib/utils"
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
@ -26,7 +26,11 @@ export async function buyQuota(
|
||||
export async function getPackage(): Promise<PackageResponse> {
|
||||
try {
|
||||
const resp = await axios.get(`/package`);
|
||||
return resp.data as PackageResponse;
|
||||
return {
|
||||
status: resp.data.status,
|
||||
cert: resp.data.data.cert,
|
||||
teenager: resp.data.data.teenager,
|
||||
}
|
||||
} catch (e) {
|
||||
console.debug(e);
|
||||
return { status: false, cert: false, teenager: false };
|
||||
|
@ -77,12 +77,16 @@ const resources = {
|
||||
},
|
||||
pkg: {
|
||||
"title": "Packages",
|
||||
"go": "Go to",
|
||||
"verify": "Verify",
|
||||
"go": "Go to Verify",
|
||||
"cert": "Certification Package",
|
||||
"cert-desc": "After real-name certification, you can get 50 points (worth 5 CNY)",
|
||||
"teen": "Teenager Package",
|
||||
"teen-desc": "After real-name certification, teenagers (18 years old and below) can get an additional 150 points (worth 15 CNY)",
|
||||
"close": "Close",
|
||||
state: {
|
||||
"true": "Received",
|
||||
"false": "Not Received",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -152,13 +156,17 @@ const resources = {
|
||||
},
|
||||
pkg: {
|
||||
"title": "礼包",
|
||||
"go": "前往",
|
||||
"verify": "实名认证",
|
||||
"go": "前往实名认证",
|
||||
"cert": "实名认证礼包",
|
||||
"cert-desc": "实名认证后可获得 50 点数 (价值 5 元)",
|
||||
"teen": "未成年人福利",
|
||||
"teen-desc": "实名认证后未成年人(18 周岁及以下)可额外获得 150 点数 (价值 15 元)",
|
||||
}
|
||||
"close": "关闭",
|
||||
state: {
|
||||
"true": "已领取",
|
||||
"false": "无法领取",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -10,28 +10,64 @@ import {Button} from "../components/ui/button.tsx";
|
||||
import "../assets/package.less";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
import {dialogSelector, refreshPackage} from "../store/package.ts";
|
||||
import {
|
||||
certSelector,
|
||||
closeDialog,
|
||||
dialogSelector,
|
||||
refreshPackageTask,
|
||||
setDialog,
|
||||
teenagerSelector
|
||||
} from "../store/package.ts";
|
||||
import {useEffect} from "react";
|
||||
import {Gift} from "lucide-react";
|
||||
import {Separator} from "../components/ui/separator.tsx";
|
||||
import {Badge} from "../components/ui/badge.tsx";
|
||||
|
||||
function Package() {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const open = useSelector(dialogSelector);
|
||||
const cert = useSelector(certSelector);
|
||||
const teenager = useSelector(teenagerSelector);
|
||||
|
||||
useEffect(() => {
|
||||
refreshPackage(dispatch);
|
||||
refreshPackageTask(dispatch);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<Dialog open={open} onOpenChange={
|
||||
(open) => dispatch(setDialog(open))
|
||||
}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit profile</DialogTitle>
|
||||
<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
<DialogTitle>{ t('pkg.title') }</DialogTitle>
|
||||
<DialogDescription asChild>
|
||||
<div className={`package-wrapper`}>
|
||||
<div className={`package`}>
|
||||
<div className={`package-title`}>
|
||||
<Gift className={`h-4 w-4`} />
|
||||
{ t('pkg.cert') }
|
||||
<Badge variant={cert ? 'default' : 'outline'}>{ t(`pkg.state.${Boolean(cert)}`) }</Badge>
|
||||
</div>
|
||||
<div className={`package-content`}>{ t('pkg.cert-desc') }</div>
|
||||
</div>
|
||||
<Separator orientation={`horizontal`} />
|
||||
<div className={`package`}>
|
||||
<div className={`package-title`}>
|
||||
<Gift className={`h-4 w-4`} />
|
||||
{ t('pkg.teen') }
|
||||
<Badge variant={teenager ? 'default' : 'outline'}>{ t(`pkg.state.${Boolean(teenager)}`) }</Badge>
|
||||
</div>
|
||||
<div className={`package-content`}>{ t('pkg.teen-desc') }</div>
|
||||
</div>
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button>Save changes</Button>
|
||||
<Button variant={`outline`} onClick={() => dispatch(closeDialog())}>{ t('pkg.close') }</Button>
|
||||
<Button variant={`default`} onClick={
|
||||
() => window.open("https://deeptrain.lightxi.com/home/package")
|
||||
}>{ t('pkg.go') }</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
@ -35,13 +35,16 @@ export const dialogSelector = (state: any): boolean => state.package.dialog;
|
||||
export const certSelector = (state: any): boolean => state.package.cert;
|
||||
export const teenagerSelector = (state: any): boolean => state.package.teenager;
|
||||
|
||||
export const refreshPackage = (dispatch: any) => {
|
||||
setInterval(async () => {
|
||||
const current = new Date().getTime(); //@ts-ignore
|
||||
if (window.hasOwnProperty("package") && (current - window.package < 2500)) return; //@ts-ignore
|
||||
window.package = current;
|
||||
const refreshPackage = async (dispatch: any) => {
|
||||
const current = new Date().getTime(); //@ts-ignore
|
||||
if (window.hasOwnProperty("package") && (current - window.package < 2500)) return; //@ts-ignore
|
||||
window.package = current;
|
||||
|
||||
const response = await getPackage();
|
||||
if (response.status) dispatch(refreshState(response));
|
||||
}, 10000);
|
||||
const response = await getPackage();
|
||||
if (response.status) dispatch(refreshState(response));
|
||||
}
|
||||
|
||||
export const refreshPackageTask = (dispatch: any) => {
|
||||
setInterval(() => refreshPackage(dispatch), 5000);
|
||||
refreshPackage(dispatch).then();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user