♻️ refactor(core): Restructure project for better module separation

This commit is contained in:
web@ppanel
2024-12-26 02:53:28 +07:00
parent 17ce96a423
commit 9d0cb8b869
368 changed files with 152606 additions and 47239 deletions
-40
View File
@@ -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
-39
View File
@@ -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
View File
@@ -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.
+2 -2
View File
@@ -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> 查看结果。
+10 -4
View File
@@ -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 -1
View File
@@ -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';
+9 -3
View File
@@ -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';
+14 -8
View File
@@ -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';
+12 -6
View File
@@ -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');
}
}
}}
>
+1 -1
View File
@@ -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';
+11 -6
View File
@@ -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';
+19 -13
View File
@@ -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');
+2 -2
View File
@@ -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 -1
View File
@@ -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();
+11 -7
View File
@@ -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>
+1 -1
View File
@@ -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,
+6 -5
View File
@@ -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,
+6 -5
View File
@@ -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({
+7 -6
View File
@@ -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({
+6 -5
View File
@@ -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({
+18 -8
View File
@@ -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} />
+20
View File
@@ -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
}
+3 -3
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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';
+1 -1
View File
@@ -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 -1
View File
@@ -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';
+9 -3
View File
@@ -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' />
+3 -2
View File
@@ -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>
);
+5 -4
View File
@@ -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>
);
+34 -23
View File
@@ -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>
),
)}
</>
);
})()}
+11 -8
View File
@@ -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));
+4 -3
View File
@@ -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>,
) {
+7 -6
View File
@@ -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>
+3 -3
View File
@@ -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';
+3 -2
View File
@@ -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.
-12
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 [
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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, {
+2 -2
View File
@@ -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) {