♻️ refactor(core): Restructure project for better module separation
This commit is contained in:
@@ -1,40 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"entry": "./locales/en-US",
|
||||
"entryLocale": "en-US",
|
||||
"experimental": {
|
||||
"jsonMode": true
|
||||
},
|
||||
"markdown": {
|
||||
"entry": ["./README.md"],
|
||||
"entryLocale": "en-US",
|
||||
"outputLocales": ["zh-CN"]
|
||||
},
|
||||
"modelName": "gpt-4o",
|
||||
"output": "./locales",
|
||||
"outputLocales": [
|
||||
"en-US",
|
||||
"cs-CZ",
|
||||
"de-DE",
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"fa-IR",
|
||||
"fi-FI",
|
||||
"fr-FR",
|
||||
"hi-IN",
|
||||
"hu-HU",
|
||||
"ja-JP",
|
||||
"ko-KR",
|
||||
"no-NO",
|
||||
"pl-PL",
|
||||
"pt-BR",
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"th-TH",
|
||||
"tr-TR",
|
||||
"uk-UA",
|
||||
"vi-VN",
|
||||
"zh-CN",
|
||||
"zh-HK"
|
||||
]
|
||||
}
|
||||
+2
-2
@@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
|
||||
cd ppanel-web
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
bun install
|
||||
|
||||
# Run the development server
|
||||
cd apps/user
|
||||
pnpm dev
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open <http://localhost:3000> with your browser to see the result.
|
||||
|
||||
@@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
|
||||
cd ppanel-web
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
bun install
|
||||
|
||||
# 运行开发服务器
|
||||
cd apps/user
|
||||
pnpm dev
|
||||
bun dev
|
||||
```
|
||||
|
||||
在浏览器中打开 <http://localhost:3000> 查看结果。
|
||||
|
||||
@@ -4,14 +4,20 @@ import { Empty } from '@/components/empty';
|
||||
import { ProList } from '@/components/pro-list';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { queryUserAffiliate } from '@/services/user/user';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@workspace/ui/components/card';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { Copy } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useState } from 'react';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Page() {
|
||||
const t = useTranslations('affiliate');
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import { Empty } from '@/components/empty';
|
||||
import { queryAnnouncement } from '@/services/user/announcement';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { Timeline } from '@shadcn/ui/timeline';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Timeline } from '@workspace/ui/components/timeline';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
|
||||
export default function Page() {
|
||||
const { data } = useQuery({
|
||||
|
||||
@@ -4,8 +4,13 @@ import { Display } from '@/components/display';
|
||||
import { queryApplicationConfig } from '@/services/user/subscribe';
|
||||
import { queryUserSubscribe } from '@/services/user/user';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { getNextResetDate, isBrowser } from '@repo/ui/utils';
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@shadcn/ui/accordion';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from '@workspace/ui/components/accordion';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -16,19 +21,19 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from '@shadcn/ui/alert-dialog';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { differenceInDays } from '@shadcn/ui/lib/date-fns';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
} from '@workspace/ui/components/alert-dialog';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
|
||||
import { getNextResetDate, isBrowser } from '@workspace/ui/utils';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { QRCodeCanvas } from 'qrcode.react';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { getStat } from '@/services/common/common';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client';
|
||||
|
||||
import { queryDocumentDetail } from '@/services/user/document';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { Avatar, AvatarFallback } from '@shadcn/ui/avatar';
|
||||
import { buttonVariants } from '@shadcn/ui/button';
|
||||
import { useOutsideClick } from '@shadcn/ui/hooks/use-outside-click';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Avatar, AvatarFallback } from '@workspace/ui/components/avatar';
|
||||
import { buttonVariants } from '@workspace/ui/components/button';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
import { useOutsideClick } from '@workspace/ui/hooks/use-outside-click';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { RefObject, useEffect, useId, useRef, useState } from 'react';
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import { queryDocumentList } from '@/services/user/document';
|
||||
import { getTutorialList } from '@/utils/tutorial';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import { DocumentButton } from './document-button';
|
||||
import { TutorialButton } from './tutorial-button';
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { getTutorial } from '@/utils/tutorial';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { Avatar, AvatarFallback } from '@shadcn/ui/avatar';
|
||||
import { buttonVariants } from '@shadcn/ui/button';
|
||||
import { useOutsideClick } from '@shadcn/ui/hooks/use-outside-click';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Avatar, AvatarFallback } from '@workspace/ui/components/avatar';
|
||||
import { buttonVariants } from '@workspace/ui/components/button';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
import { useOutsideClick } from '@workspace/ui/hooks/use-outside-click';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { RefObject, useEffect, useId, useRef, useState } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Announcement from '@/components/announcement';
|
||||
import { SidebarInset, SidebarProvider } from '@shadcn/ui/sidebar';
|
||||
import { SidebarInset, SidebarProvider } from '@workspace/ui/components/sidebar';
|
||||
import { cookies } from 'next/headers';
|
||||
import { SidebarLeft } from './sidebar-left';
|
||||
import { SidebarRight } from './sidebar-right';
|
||||
|
||||
@@ -4,9 +4,15 @@ import { Display } from '@/components/display';
|
||||
import { Empty } from '@/components/empty';
|
||||
import { ProList, ProListActions } from '@/components/pro-list';
|
||||
import { closeOrder, queryOrderList } from '@/services/user/order';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { Button, buttonVariants } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { Button, buttonVariants } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@workspace/ui/components/card';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { useRef } from 'react';
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkoutOrder, preCreateOrder, purchase } from '@/services/user/order';
|
||||
import { getAvailablePaymentMethods } from '@/services/user/payment';
|
||||
import { Badge } from '@shadcn/ui/badge';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent } from '@shadcn/ui/card';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@shadcn/ui/dialog';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { Label } from '@shadcn/ui/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@shadcn/ui/radio-group';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Badge } from '@workspace/ui/components/badge';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent } from '@workspace/ui/components/card';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@workspace/ui/components/dialog';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { LoaderCircle } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkoutOrder, recharge } from '@/services/user/order';
|
||||
import { getAvailablePaymentMethods } from '@/services/user/payment';
|
||||
import { EnhancedInput } from '@repo/ui/enhanced-input';
|
||||
import { unitConversion } from '@repo/ui/utils';
|
||||
import { Button, ButtonProps } from '@shadcn/ui/button';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button, ButtonProps } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -13,10 +12,11 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@shadcn/ui/dialog';
|
||||
import { Label } from '@shadcn/ui/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@shadcn/ui/radio-group';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
} from '@workspace/ui/components/dialog';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
|
||||
import { unitConversion } from '@workspace/ui/utils';
|
||||
import { LoaderCircle } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/image';
|
||||
|
||||
@@ -3,15 +3,21 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkoutOrder, preCreateOrder, renewal } from '@/services/user/order';
|
||||
import { getAvailablePaymentMethods } from '@/services/user/payment';
|
||||
import { Badge } from '@shadcn/ui/badge';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent } from '@shadcn/ui/card';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@shadcn/ui/dialog';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { Label } from '@shadcn/ui/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@shadcn/ui/radio-group';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Badge } from '@workspace/ui/components/badge';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent } from '@workspace/ui/components/card';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@workspace/ui/components/dialog';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { LoaderCircle } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
|
||||
@@ -4,7 +4,8 @@ import { Display } from '@/components/display';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkoutOrder, resetTraffic } from '@/services/user/order';
|
||||
import { getAvailablePaymentMethods } from '@/services/user/payment';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -12,10 +13,9 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@shadcn/ui/dialog';
|
||||
import { Label } from '@shadcn/ui/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@shadcn/ui/radio-group';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
} from '@workspace/ui/components/dialog';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
|
||||
import { LoaderCircle } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
|
||||
@@ -4,14 +4,20 @@ import { Display } from '@/components/display';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkoutOrder, queryOrderDetail } from '@/services/user/order';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { Badge } from '@shadcn/ui/badge';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { addMinutes, format } from '@shadcn/ui/lib/date-fns';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Badge } from '@workspace/ui/components/badge';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@workspace/ui/components/card';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { useCountDown } from 'ahooks';
|
||||
import { addMinutes, format } from 'date-fns';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { QRCodeCanvas } from 'qrcode.react';
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import { updateUserPassword } from '@/services/user/user';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default function ChangePassword() {
|
||||
const t = useTranslations('profile.accountSettings');
|
||||
|
||||
@@ -2,13 +2,21 @@
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { updateUserNotify } from '@/services/user/user';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Switch } from '@shadcn/ui/switch';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@workspace/ui/components/form';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
import { z } from 'zod';
|
||||
|
||||
const FormSchema = z.object({
|
||||
enable_balance_notify: z.boolean(),
|
||||
|
||||
@@ -2,15 +2,23 @@
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { bindTelegram, unbindTelegram, updateUserNotifySetting } from '@/services/user/user';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Switch } from '@shadcn/ui/switch';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
import { z } from 'zod';
|
||||
|
||||
const FormSchema = z.object({
|
||||
telegram: z.number().nullish(),
|
||||
@@ -70,7 +78,9 @@ export default function NotifySettings() {
|
||||
await getUserInfo();
|
||||
} else {
|
||||
const { data } = await bindTelegram();
|
||||
data.data?.url && window.open(data.data.url, '_blank');
|
||||
if (data.data?.url) {
|
||||
window.open(data.data.url, '_blank');
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from '@shadcn/ui/sidebar';
|
||||
} from '@workspace/ui/components/sidebar';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
import { Display } from '@/components/display';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { isBrowser } from '@repo/ui/utils';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { Sidebar, SidebarContent } from '@shadcn/ui/sidebar';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@shadcn/ui/tooltip';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import { Sidebar, SidebarContent } from '@workspace/ui/components/sidebar';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@workspace/ui/components/tooltip';
|
||||
import { isBrowser } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import { toast } from 'sonner';
|
||||
import Recharge from './order/recharge';
|
||||
|
||||
export function SidebarRight({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { Display } from '@/components/display';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
interface SubscribeBillingProps {
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
import { Display } from '@/components/display';
|
||||
import { querySubscribeGroupList, querySubscribeList } from '@/services/user/subscribe';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@shadcn/ui/card';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@workspace/ui/components/card';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useState } from 'react';
|
||||
|
||||
|
||||
@@ -10,10 +10,15 @@ import {
|
||||
updateUserTicketStatus,
|
||||
} from '@/services/user/ticket';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { ConfirmButton } from '@repo/ui/confirm-button';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@workspace/ui/components/card';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -22,7 +27,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@shadcn/ui/dialog';
|
||||
} from '@workspace/ui/components/dialog';
|
||||
import {
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
@@ -30,17 +35,18 @@ import {
|
||||
DrawerFooter,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
} from '@shadcn/ui/drawer';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { Label } from '@shadcn/ui/label';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { ScrollArea } from '@shadcn/ui/scroll-area';
|
||||
import { Textarea } from '@shadcn/ui/textarea';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
} from '@workspace/ui/components/drawer';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { ScrollArea } from '@workspace/ui/components/scroll-area';
|
||||
import { Textarea } from '@workspace/ui/components/textarea';
|
||||
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import NextImage from 'next/legacy/image';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export default function Page() {
|
||||
const t = useTranslations('ticket');
|
||||
|
||||
@@ -4,12 +4,12 @@ import { Display } from '@/components/display';
|
||||
import { ProList, ProListActions } from '@/components/pro-list';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { queryUserBalanceLog } from '@/services/user/user';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRef } from 'react';
|
||||
|
||||
import { Empty } from '@/components/empty';
|
||||
import { formatDate } from '@repo/ui/utils';
|
||||
import { formatDate } from '@workspace/ui/utils';
|
||||
import Recharge from '../order/recharge';
|
||||
|
||||
export default function Page() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getTos } from '@/services/common/common';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
|
||||
export default async function Page() {
|
||||
const { data } = await getTos();
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
import Link from 'next/link';
|
||||
|
||||
import LanguageSwitch from '@/components/language-switch';
|
||||
import ThemeSwitch from '@/components/theme-switch';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
|
||||
import { LoginIcon } from '@repo/ui/lotties';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import LoginLottie from '@workspace/ui/lotties/login.json';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
import Link from 'next/link';
|
||||
import UserAuthForm from './user-auth-form';
|
||||
|
||||
export default function Page() {
|
||||
@@ -25,7 +24,12 @@ export default function Page() {
|
||||
<Image src={site.site_logo} height={48} width={48} alt='logo' unoptimized />
|
||||
<span className='text-2xl font-semibold'>{site.site_name}</span>
|
||||
</Link>
|
||||
<LoginIcon className='mx-auto hidden w-[275px] md:w-1/2 lg:block xl:w-[500px]' />
|
||||
<DotLottieReact
|
||||
data={LoginLottie}
|
||||
autoplay
|
||||
loop
|
||||
className='mx-auto hidden w-[275px] md:w-1/2 lg:block xl:w-[500px]'
|
||||
/>
|
||||
<p className='hidden w-[275px] text-center md:w-1/2 lg:block xl:w-[500px]'>
|
||||
{site.site_desc}
|
||||
</p>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { checkUser, resetPassword, userLogin, userRegister } from '@/services/common/auth';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { ReactNode, useState, useTransition } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import {
|
||||
NEXT_PUBLIC_DEFAULT_USER_EMAIL,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default function UserCheckForm({
|
||||
loading,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import CloudFlareTurnstile from './turnstile';
|
||||
|
||||
export default function UserLoginForm({
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { sendEmailCode } from '@/services/common/common';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
import { useCountDown } from 'ahooks';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import CloudFlareTurnstile from './turnstile';
|
||||
|
||||
export default function UserRegisterForm({
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { sendEmailCode } from '@/services/common/common';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form';
|
||||
import { Input } from '@shadcn/ui/input';
|
||||
import { useForm } from '@shadcn/ui/lib/react-hook-form';
|
||||
import { z, zodResolver } from '@shadcn/ui/lib/zod';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
|
||||
import { Input } from '@workspace/ui/components/input';
|
||||
import { useCountDown } from 'ahooks';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import CloudFlareTurnstile from './turnstile';
|
||||
|
||||
export default function UserResetForm({
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
import Providers from '@/components/providers';
|
||||
import { geistMono, geistSans } from '@/config/fonts';
|
||||
import { getGlobalConfig } from '@/services/common/common';
|
||||
import { queryUserInfo } from '@/services/user/user';
|
||||
import '@shadcn/ui/globals.css';
|
||||
import { Toaster } from '@shadcn/ui/sonner';
|
||||
import { Toaster } from '@workspace/ui/components/sonner';
|
||||
import '@workspace/ui/globals.css';
|
||||
import { getLangDir } from '@workspace/ui/hooks/use-lang-dir';
|
||||
import { NextIntlClientProvider } from 'next-intl';
|
||||
import { getLocale, getMessages } from 'next-intl/server';
|
||||
import { PublicEnvScript } from 'next-runtime-env';
|
||||
import { unstable_noStore as noStore } from 'next/cache';
|
||||
import { Geist, Geist_Mono } from 'next/font/google';
|
||||
import { cookies } from 'next/headers';
|
||||
import { Metadata, Viewport } from 'next/types';
|
||||
import NextTopLoader from 'nextjs-toploader';
|
||||
import React from 'react';
|
||||
import rtlDetect from 'rtl-detect';
|
||||
|
||||
const fontSans = Geist({
|
||||
subsets: ['latin'],
|
||||
variable: '--font-sans',
|
||||
});
|
||||
|
||||
const fontMono = Geist_Mono({
|
||||
subsets: ['latin'],
|
||||
variable: '--font-mono',
|
||||
});
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
noStore();
|
||||
@@ -68,7 +78,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||
try {
|
||||
config = await getGlobalConfig({ skipErrorHandler: true }).then((res) => res.data.data);
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
console.log('Error fetching global config:', error);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -77,17 +87,17 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||
Authorization: (await cookies()).get('Authorization')?.value,
|
||||
}).then((res) => res.data.data);
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
console.log('Error fetching user info:', error);
|
||||
}
|
||||
|
||||
return (
|
||||
<html suppressHydrationWarning lang={locale} dir={rtlDetect.getLangDir(locale)}>
|
||||
<html suppressHydrationWarning lang={locale} dir={getLangDir(locale)}>
|
||||
<head>
|
||||
<PublicEnvScript />
|
||||
</head>
|
||||
<body
|
||||
suppressHydrationWarning
|
||||
className={`${geistSans.variable} ${geistMono.variable} size-full min-h-[calc(100dvh-env(safe-area-inset-top))] antialiased`}
|
||||
className={`${fontSans.variable} ${fontMono.variable} size-full min-h-[calc(100dvh-env(safe-area-inset-top))] font-sans antialiased`}
|
||||
>
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<NextTopLoader showSpinner={false} />
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"hooks": "@/hooks",
|
||||
"lib": "@/lib",
|
||||
"utils": "@workspace/ui/lib/utils",
|
||||
"ui": "@workspace/ui/components"
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"rsc": true,
|
||||
"style": "new-york",
|
||||
"tailwind": {
|
||||
"config": "../../packages/ui/tailwind.config.ts",
|
||||
"css": "../../packages/ui/src/styles/globals.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true
|
||||
},
|
||||
"tsx": true
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { queryAnnouncement } from '@/services/user/announcement';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Markdown } from '@repo/ui/markdown';
|
||||
import { Card } from '@shadcn/ui/card';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@shadcn/ui/dialog';
|
||||
import { Card } from '@workspace/ui/components/card';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@workspace/ui/components/dialog';
|
||||
import { Markdown } from '@workspace/ui/custom-components/markdown';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { Empty } from '../empty';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { formatBytes, unitConversion } from '@repo/ui/utils';
|
||||
import { formatBytes, unitConversion } from '@workspace/ui/utils';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
type DisplayType = 'currency' | 'traffic' | 'number';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { default as _Empty } from '@repo/ui/empty';
|
||||
import { default as _Empty } from '@workspace/ui/custom-components/empty';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '@/config/constants';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { buttonVariants } from '@shadcn/ui/button';
|
||||
import { buttonVariants } from '@workspace/ui/components/button';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/legacy/image';
|
||||
import Link from 'next/link';
|
||||
|
||||
@@ -3,8 +3,14 @@
|
||||
import { locales } from '@/config/constants';
|
||||
import { setLocale } from '@/utils/common';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { getCountry } from '@repo/ui/utils';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@workspace/ui/components/select';
|
||||
import { getCountry } from '@workspace/ui/utils';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
@@ -21,7 +27,7 @@ export default function LanguageSwitch() {
|
||||
|
||||
return (
|
||||
<Select defaultValue={locale} onValueChange={handleLanguageChange}>
|
||||
<SelectTrigger className='hover:bg-accent hover:text-accent-foreground w-auto border-none bg-transparent p-2 focus:ring-0 [&>svg]:hidden'>
|
||||
<SelectTrigger className='hover:bg-accent hover:text-accent-foreground w-auto border-none bg-transparent p-2 shadow-none focus:ring-0 [&>svg]:hidden'>
|
||||
<SelectValue>
|
||||
<div className='flex items-center'>
|
||||
<Icon icon={`flagpack:${country?.alpha2.toLowerCase()}`} className='!size-5' />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { GlobalMapIcon } from '@repo/ui/lotties';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import GlobalMapLottie from '@workspace/ui/lotties/global-map.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
@@ -40,7 +41,7 @@ export function GlobalMap() {
|
||||
delay: 0.4,
|
||||
}}
|
||||
>
|
||||
<GlobalMapIcon className='-mt-[25%] w-full' />
|
||||
<DotLottieReact className='w-full scale-150' data={GlobalMapLottie} autoplay loop />
|
||||
</motion.div>
|
||||
</motion.section>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { NetworkSecurityIcon } from '@repo/ui/lotties';
|
||||
import { HoverBorderGradient } from '@shadcn/ui/hover-border-gradient';
|
||||
import { TextGenerateEffect } from '@shadcn/ui/text-generate-effect';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import { HoverBorderGradient } from '@workspace/ui/components/hover-border-gradient';
|
||||
import { TextGenerateEffect } from '@workspace/ui/components/text-generate-effect';
|
||||
import NetworkSecurityLottie from '@workspace/ui/lotties/network-security.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
@@ -54,7 +55,7 @@ export function Hero() {
|
||||
viewport={{ once: true, amount: 0.3 }}
|
||||
className='flex w-full'
|
||||
>
|
||||
<NetworkSecurityIcon />
|
||||
<DotLottieReact data={NetworkSecurityLottie} autoplay loop />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
@@ -4,14 +4,15 @@ import { SubscribeDetail } from '@/app/(main)/(user)/subscribe/detail';
|
||||
import { Display } from '@/components/display';
|
||||
import { getSubscription } from '@/services/common/common';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@shadcn/ui/card';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@workspace/ui/components/card';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { Key, ReactNode } from 'react';
|
||||
|
||||
export function ProductShowcase() {
|
||||
const t = useTranslations('index');
|
||||
@@ -75,25 +76,35 @@ export function ProductShowcase() {
|
||||
return (
|
||||
<>
|
||||
{description && <li className='text-muted-foreground'>{description}</li>}
|
||||
{features.map((feature, index) => (
|
||||
<li
|
||||
className={cn('flex items-center gap-2', {
|
||||
'text-muted-foreground line-through': feature.type === 'destructive',
|
||||
})}
|
||||
key={index}
|
||||
>
|
||||
{feature.icon && (
|
||||
<Icon
|
||||
icon={feature.icon}
|
||||
className={cn('text-primary size-5', {
|
||||
'text-green-500': feature.type === 'success',
|
||||
'text-destructive': feature.type === 'destructive',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{feature.label}
|
||||
</li>
|
||||
))}
|
||||
{features.map(
|
||||
(
|
||||
feature: {
|
||||
type: string;
|
||||
icon: string;
|
||||
label: ReactNode;
|
||||
},
|
||||
index: Key,
|
||||
) => (
|
||||
<li
|
||||
className={cn('flex items-center gap-2', {
|
||||
'text-muted-foreground line-through':
|
||||
feature.type === 'destructive',
|
||||
})}
|
||||
key={index}
|
||||
>
|
||||
{feature.icon && (
|
||||
<Icon
|
||||
icon={feature.icon}
|
||||
className={cn('text-primary size-5', {
|
||||
'text-green-500': feature.type === 'success',
|
||||
'text-destructive': feature.type === 'destructive',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{feature.label}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { getStat } from '@/services/common/common';
|
||||
import { LocationsIcon, ServersIcon, UsersIcon } from '@repo/ui/lotties';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import LocationsLittie from '@workspace/ui/lotties/locations.json';
|
||||
import ServersLottie from '@workspace/ui/lotties/servers.json';
|
||||
import UsersLottie from '@workspace/ui/lotties/users.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -25,17 +28,17 @@ export function Stats() {
|
||||
{
|
||||
name: t('users'),
|
||||
number: data?.user || 999,
|
||||
icon: <UsersIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={UsersLottie} autoplay loop />,
|
||||
},
|
||||
{
|
||||
name: t('servers'),
|
||||
number: data?.server || 30,
|
||||
icon: <ServersIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={ServersLottie} autoplay loop />,
|
||||
},
|
||||
{
|
||||
name: t('locations'),
|
||||
number: data?.country || 10,
|
||||
icon: <LocationsIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={LocationsLittie} autoplay loop />,
|
||||
},
|
||||
];
|
||||
return (
|
||||
@@ -77,12 +80,12 @@ function CountUp({ end, duration = 2000 }: { end: number; duration?: number }) {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
let startTime;
|
||||
let animationFrame;
|
||||
let startTime: number;
|
||||
let animationFrame: number;
|
||||
|
||||
const easeOutQuad = (t) => t * (2 - t);
|
||||
const easeOutQuad = (t: number) => t * (2 - t);
|
||||
|
||||
const updateCount = (timestamp) => {
|
||||
const updateCount = (timestamp: number) => {
|
||||
if (!startTime) startTime = timestamp;
|
||||
const progress = timestamp - startTime;
|
||||
const easedProgress = easeOutQuad(Math.min(progress / duration, 1));
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use client';
|
||||
import { ProList as _ProList, ProListProps } from '@repo/ui/pro-list';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export { type ProListActions, type ProListProps } from '@repo/ui/pro-list';
|
||||
import { ProList as _ProList, ProListProps } from '@workspace/ui/custom-components/pro-list';
|
||||
import { useTranslations } from 'next-intl';
|
||||
export { type ProListActions, type ProListProps } from '@workspace/ui/custom-components/pro-list';
|
||||
|
||||
export function ProList<TData, TValue extends Record<string, unknown>>(
|
||||
props: ProListProps<TData, TValue>,
|
||||
) {
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
'use client';
|
||||
|
||||
import { MoonIcon, SunIcon } from '@repo/ui/lotties';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@shadcn/ui/dropdown-menu';
|
||||
} from '@workspace/ui/components/dropdown-menu';
|
||||
import MoonLottie from '@workspace/ui/lotties/moon.json';
|
||||
import SunLottie from '@workspace/ui/lotties/sun.json';
|
||||
import { useTheme } from 'next-themes';
|
||||
|
||||
export default function ThemeSwitch() {
|
||||
const { setTheme } = useTheme();
|
||||
const { setTheme, resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant='ghost' size='icon'>
|
||||
<MoonIcon className='size-8 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' />
|
||||
<SunIcon className='roate-90 absolute size-8 scale-0 transition-all dark:rotate-0 dark:scale-100' />
|
||||
<DotLottieReact data={resolvedTheme === 'dark' ? MoonLottie : SunLottie} autoplay loop />
|
||||
<span className='sr-only'>Toggle theme</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
@@ -4,8 +4,8 @@ import { navs } from '@/config/navs';
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { Logout } from '@/utils/common';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@shadcn/ui/avatar';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@workspace/ui/components/avatar';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@shadcn/ui/dropdown-menu';
|
||||
} from '@workspace/ui/components/dropdown-menu';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { env } from 'next-runtime-env';
|
||||
import i18nConfig from '../.i18nrc.json';
|
||||
import packageJSON from '../package.json';
|
||||
|
||||
export const locales = i18nConfig.outputLocales;
|
||||
export const locales = packageJSON.i18n.outputLocales;
|
||||
export const defaultLocale = packageJSON.i18n.entry;
|
||||
|
||||
export const NEXT_PUBLIC_DEFAULT_LANGUAGE = env('NEXT_PUBLIC_DEFAULT_LANGUAGE') || locales[0];
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
import localFont from 'next/font/local';
|
||||
|
||||
export const geistSans = localFont({
|
||||
src: './GeistVF.woff',
|
||||
variable: '--font-geist-sans',
|
||||
weight: '100 900',
|
||||
});
|
||||
export const geistMono = localFont({
|
||||
src: './GeistMonoVF.woff',
|
||||
variable: '--font-geist-mono',
|
||||
weight: '100 900',
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SITE_URL } from '@/config/constants';
|
||||
import { queryUserInfo } from '@/services/user/user';
|
||||
import { extractDomain } from '@repo/ui/utils';
|
||||
import { extractDomain } from '@workspace/ui/utils';
|
||||
import { create } from 'zustand';
|
||||
|
||||
export interface GlobalStore {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { nextJsConfig } from '@repo/eslint-config/next-js';
|
||||
import { nextJsConfig } from '@workspace/eslint-config/next-js';
|
||||
|
||||
/** @type {import("eslint").Linter.Config} */
|
||||
export default [
|
||||
|
||||
@@ -4,7 +4,7 @@ import createNextIntlPlugin from 'next-intl/plugin';
|
||||
const withNextIntl = createNextIntlPlugin('./locales/request.ts');
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
transpilePackages: ['@shadcn/ui', '@repo/ui'],
|
||||
transpilePackages: ['@workspace/ui'],
|
||||
output: 'standalone',
|
||||
images: {
|
||||
remotePatterns: [
|
||||
|
||||
+55
-16
@@ -4,27 +4,24 @@
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next dev --turbopack -p 3001",
|
||||
"lint": "next lint --max-warnings 0 && tsc --noEmit",
|
||||
"lint": "next lint && tsc --noEmit",
|
||||
"locale": "lobe-i18n --with-md",
|
||||
"openapi": "openapi2ts",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/react": "^5.1.0",
|
||||
"@repo/ui": "workspace:*",
|
||||
"@shadcn/ui": "workspace:*",
|
||||
"@stripe/react-stripe-js": "^3.1.0",
|
||||
"@stripe/stripe-js": "^5.3.0",
|
||||
"@tanstack/react-query": "^5.62.7",
|
||||
"@tanstack/react-query-next-experimental": "^5.62.7",
|
||||
"@stripe/react-stripe-js": "^3.1.1",
|
||||
"@stripe/stripe-js": "^5.4.0",
|
||||
"@tanstack/react-query": "^5.62.10",
|
||||
"@tanstack/react-query-next-experimental": "^5.62.10",
|
||||
"@workspace/ui": "workspace:*",
|
||||
"ahooks": "^3.8.4",
|
||||
"axios": "^1.7.9",
|
||||
"crypto-js": "^4.2.0",
|
||||
"framer-motion": "^11.14.4",
|
||||
"lucide-react": "^0.468.0",
|
||||
"mathjs": "^14.0.1",
|
||||
"next": "^15.1.0",
|
||||
"next-intl": "^3.26.1",
|
||||
"framer-motion": "^11.15.0",
|
||||
"lucide-react": "^0.469.0",
|
||||
"next": "^15.1.2",
|
||||
"next-intl": "^3.26.3",
|
||||
"next-runtime-env": "^3.2.2",
|
||||
"next-themes": "^0.4.4",
|
||||
"nextjs-toploader": "^3.7.15",
|
||||
@@ -39,13 +36,55 @@
|
||||
"zustand": "^5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/eslint-config": "workspace:*",
|
||||
"@repo/typescript-config": "workspace:*",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react": "^19.0.2",
|
||||
"@types/react-copy-to-clipboard": "^5.0.7",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"@types/rtl-detect": "^1.0.3",
|
||||
"@workspace/eslint-config": "workspace:*",
|
||||
"@workspace/typescript-config": "workspace:*",
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"i18n": {
|
||||
"entry": "./locales/en-US",
|
||||
"entryLocale": "en-US",
|
||||
"output": "./locales",
|
||||
"outputLocales": [
|
||||
"cs-CZ",
|
||||
"de-DE",
|
||||
"en-US",
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"fa-IR",
|
||||
"fi-FI",
|
||||
"fr-FR",
|
||||
"hi-IN",
|
||||
"hu-HU",
|
||||
"ja-JP",
|
||||
"ko-KR",
|
||||
"no-NO",
|
||||
"pl-PL",
|
||||
"pt-BR",
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"th-TH",
|
||||
"tr-TR",
|
||||
"uk-UA",
|
||||
"vi-VN",
|
||||
"zh-CN",
|
||||
"zh-HK"
|
||||
],
|
||||
"modelName": "gpt-4o",
|
||||
"experimental": {
|
||||
"jsonMode": true
|
||||
},
|
||||
"markdown": {
|
||||
"entry": [
|
||||
"./README.md"
|
||||
],
|
||||
"outputLocales": [
|
||||
"zh-CN"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
export { default } from '@workspace/ui/postcss.config';
|
||||
|
||||
@@ -1,14 +1 @@
|
||||
import sharedConfig from '@shadcn/ui/tailwind.config';
|
||||
import type { Config } from 'tailwindcss';
|
||||
|
||||
const config: Config = {
|
||||
...sharedConfig,
|
||||
content: [
|
||||
'./pages/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./app/**/*.{ts,tsx}',
|
||||
'../../packages/shadcn/src/components/**/*.{ts,tsx}',
|
||||
'../../packages/ui/src/**/*.{ts,tsx}',
|
||||
],
|
||||
};
|
||||
export default config;
|
||||
export * from '@workspace/ui/tailwind.config';
|
||||
|
||||
+10
-5
@@ -1,18 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"plugins": [{ "name": "next" }],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
"@/*": ["./*"],
|
||||
"@workspace/ui/*": ["../../packages/ui/src/*"]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@repo/typescript-config/nextjs.json",
|
||||
"extends": "@workspace/typescript-config/nextjs.json",
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"next.config.mjs",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.mjs",
|
||||
".next/types/**/*.ts",
|
||||
"services/**/typings.d.ts"
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { locales, NEXT_PUBLIC_DEFAULT_LANGUAGE } from '@/config/constants';
|
||||
import { isBrowser } from '@repo/ui/utils';
|
||||
import { isBrowser } from '@workspace/ui/utils';
|
||||
import Cookies from 'universal-cookie';
|
||||
|
||||
const cookies = new Cookies(null, {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SITE_URL } from '@/config/constants';
|
||||
import { getTranslations } from '@/locales/utils';
|
||||
import { isBrowser } from '@repo/ui/utils';
|
||||
import { toast } from '@shadcn/ui/lib/sonner';
|
||||
import { isBrowser } from '@workspace/ui/utils';
|
||||
import requset, { InternalAxiosRequestConfig } from 'axios';
|
||||
import { toast } from 'sonner';
|
||||
import { getAuthorization, Logout } from './common';
|
||||
|
||||
async function handleError(response: any) {
|
||||
|
||||
Reference in New Issue
Block a user