♻️ 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

View File

@ -1,3 +0,0 @@
module.exports = {
extends: ['@repo/commitlint-config'],
};

View File

@ -0,0 +1,89 @@
name: Publish Release Assets
on:
release:
types: [published]
permissions:
contents: write
jobs:
publish:
name: Publish Release Assets
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 'latest'
- name: Cache Bun dependencies
uses: actions/cache@v3
with:
path: |
~/.bun
key: ${{ runner.os }}-bun-cache-${{ hashFiles('**/bun.lockb') }}
restore-keys: |
${{ runner.os }}-bun-cache-
- name: Install deps
run: bun install --cache
- name: Build
run: bun run build
- name: Run publish script
run: |
chmod +x scripts/publish.sh
./scripts/publish.sh
- name: Upload tar.gz file to release
uses: softprops/action-gh-release@v2
with:
files: |
out/ppanel-admin-web.tar.gz
out/ppanel-user-web.tar.gz
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install jq
run: sudo apt-get install -y jq
- name: Extract version from package.json
id: version
run: echo "PPANEL_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_ENV
- name: Build and push Docker image for ppanel-user-web
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/ppanel-admin-web/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/ppanel-admin-web:latest
${{ secrets.DOCKER_USERNAME }}/ppanel-admin-web:${{ env.PPANEL_VERSION }}
- name: Build and push Docker image for ppanel-user-web
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/ppanel-user-web/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/ppanel-user-web:latest
${{ secrets.DOCKER_USERNAME }}/ppanel-user-web:${{ env.PPANEL_VERSION }}

View File

@ -1,66 +0,0 @@
name: Build and Publish Docker Image
on:
workflow_dispatch:
release:
types: [published]
push:
branches:
- develop
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
IMAGE_NAME:
- ppanel-user-web
- ppanel-admin-web
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract version from package.json
id: version
run: echo "VERSION=$(jq -r '.version' package.json)" >> $GITHUB_ENV
- name: Get short SHA
id: sha
run: echo "GIT_SHA=${GITHUB_SHA::8}" >> $GITHUB_ENV
- name: Build and push Docker image for main release
if: github.event_name == 'release'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/${{ matrix.IMAGE_NAME }}/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/${{ matrix.IMAGE_NAME }}:latest
${{ secrets.DOCKER_USERNAME }}/${{ matrix.IMAGE_NAME }}:${{ env.VERSION }}
- name: Build and push Docker image for develop
if: github.ref == 'refs/heads/develop'
uses: docker/build-push-action@v6
with:
context: .
file: ./docker/${{ matrix.IMAGE_NAME }}/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKER_USERNAME }}/${{ matrix.IMAGE_NAME }}:beta
${{ secrets.DOCKER_USERNAME }}/${{ matrix.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.GIT_SHA }}-beta

View File

@ -2,8 +2,10 @@ name: Build and Release
on: on:
push: push:
branches: branches: [main, next, beta]
- main
permissions:
contents: write
jobs: jobs:
release: release:
@ -12,34 +14,29 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install pnpm - name: Setup Bun
uses: pnpm/action-setup@v4 uses: oven-sh/setup-bun@v1
- name: Setup Node.js environment
uses: actions/setup-node@v4
with: with:
node-version: '20' bun-version: 'latest'
cache: 'pnpm'
- name: Cache pnpm store - name: Cache Bun dependencies
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: ~/.pnpm-store path: |
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} ~/.bun
node_modules
key: ${{ runner.os }}-bun-cache-${{ hashFiles('**/bun.lockb') }}
restore-keys: | restore-keys: |
${{ runner.os }}-pnpm-store- ${{ runner.os }}-bun-cache-
- name: Install deps - name: Install deps
run: pnpm install run: bun install
- name: Lint
run: pnpm lint
- name: Build - name: Build
run: pnpm build run: bun run build
- name: Release - name: Release
id: release id: release
run: pnpm release run: bun run release
env: env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }}

15
.gitignore vendored
View File

@ -37,3 +37,18 @@ yarn-error.log*
# Misc # Misc
.DS_Store .DS_Store
*.pem *.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

10
.npmrc
View File

@ -1,10 +0,0 @@
public-hoist-pattern[]=*typescript*
public-hoist-pattern[]=*tailwindcss*
public-hoist-pattern[]=*autoprefixer*
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*commitlint*
public-hoist-pattern[]=*semantic-release*
public-hoist-pattern[]=*@umijs/openapi*

View File

@ -1,57 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# Dependencies
node_modules
.pnp
.pnp.js
# Local env files
.env*
# Testing
coverage
# Turbo
.turbo
# Vercel
.vercel
# Build Outputs
.next/
out/
build
dist
# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Misc
.DS_Store
*.pem
# Fonts
*.woff
# Images
*.svg
*.ico
# Husky
.husky
# Docker
Dockerfile
# LICENSE
LICENSE
# Ignores
.npmrc
.gitignore
.prettierignore
public
packages/ui/src/lotties/*.json

View File

@ -1 +0,0 @@
module.exports = require('@repo/prettier-config');

View File

@ -10,6 +10,6 @@
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts", "*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts",
"*.jsx": "${capture}.js", "*.jsx": "${capture}.js",
"*.tsx": "${capture}.ts", "*.tsx": "${capture}.ts",
"package.json": "*" "README.md": "*.md, LICENSE"
} }
} }

View File

@ -58,7 +58,7 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# Install dependencies # Install dependencies
pnpm install bun install
``` ```
## 🤝 Contributing ## 🤝 Contributing

View File

@ -58,7 +58,7 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# 安装依赖 # 安装依赖
pnpm install bun install
``` ```
## 🤝 贡献 ## 🤝 贡献

40
apps/admin/.gitignore vendored
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

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"
]
}

View File

@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# Install dependencies # Install dependencies
pnpm install bun install
# Run the development server # Run the development server
cd apps/admin cd apps/admin
pnpm dev bun dev
``` ```
Open <http://localhost:3000> with your browser to see the result. Open <http://localhost:3000> with your browser to see the result.

View File

@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# 安装依赖 # 安装依赖
pnpm install bun install
# 运行开发服务器 # 运行开发服务器
cd apps/admin cd apps/admin
pnpm dev bun dev
``` ```
在浏览器中打开 <http://localhost:3000> 查看结果。 在浏览器中打开 <http://localhost:3000> 查看结果。

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import LanguageSwitch from '@/components/language-switch'; import LanguageSwitch from '@/components/language-switch';
import ThemeSwitch from '@/components/theme-switch';
import useGlobalStore from '@/config/use-global'; 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 { useTranslations } from 'next-intl';
import Image from 'next/legacy/image'; import Image from 'next/legacy/image';
import Link from 'next/link'; import Link from 'next/link';
import ThemeSwitch from '@/components/theme-switch';
import UserAuthForm from './user-auth-form'; import UserAuthForm from './user-auth-form';
export default function Page() { export default function Page() {
@ -30,7 +30,12 @@ export default function Page() {
/> />
<span className='text-2xl font-semibold'>{site.site_name}</span> <span className='text-2xl font-semibold'>{site.site_name}</span>
</Link> </Link>
<LoginIcon className='mx-auto hidden w-[275px] md:w-1/2 lg:block xl:w-[500px]' /> <DotLottieReact
className='mx-auto hidden w-full lg:block'
data={LoginLottie}
autoplay
loop
/>
<p className='hidden w-[275px] text-center 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} {site.site_desc}
</p> </p>

View File

@ -1,12 +1,11 @@
'use client'; 'use client';
import useGlobalStore from '@/config/use-global';
import { useLocale } from 'next-intl'; import { useLocale } from 'next-intl';
import { useTheme } from 'next-themes'; import { useTheme } from 'next-themes';
import { useEffect } from 'react'; import { useEffect } from 'react';
import Turnstile, { useTurnstile } from 'react-turnstile'; import Turnstile, { useTurnstile } from 'react-turnstile';
import useGlobalStore from '@/config/use-global';
export default function CloudFlareTurnstile({ export default function CloudFlareTurnstile({
id, id,
value, value,

View File

@ -7,10 +7,10 @@ import {
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { checkUser, resetPassword, userLogin, userRegister } from '@/services/common/auth'; import { checkUser, resetPassword, userLogin, userRegister } from '@/services/common/auth';
import { getRedirectUrl, setAuthorization } from '@/utils/common'; import { getRedirectUrl, setAuthorization } from '@/utils/common';
import { toast } from '@shadcn/ui/lib/sonner';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { ReactNode, useState, useTransition } from 'react'; import { ReactNode, useState, useTransition } from 'react';
import { toast } from 'sonner';
import UserCheckForm from './user-check-form'; import UserCheckForm from './user-check-form';
import UserLoginForm from './user-login-form'; import UserLoginForm from './user-login-form';
import UserRegisterForm from './user-register-form'; import UserRegisterForm from './user-register-form';

View File

@ -1,11 +1,12 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
import { Input } from '@shadcn/ui/input'; import { Input } from '@workspace/ui/components/input';
import { useForm } from '@shadcn/ui/lib/react-hook-form';
import { z, zodResolver } from '@shadcn/ui/lib/zod';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
export default function UserCheckForm({ export default function UserCheckForm({
loading, loading,

View File

@ -1,12 +1,13 @@
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
import { Input } from '@shadcn/ui/input'; import { Input } from '@workspace/ui/components/input';
import { useForm } from '@shadcn/ui/lib/react-hook-form';
import { z, zodResolver } from '@shadcn/ui/lib/zod';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import CloudFlareTurnstile from './turnstile'; import CloudFlareTurnstile from './turnstile';
export default function UserLoginForm({ export default function UserLoginForm({

View File

@ -1,15 +1,16 @@
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { sendEmailCode } from '@/services/common/common'; import { sendEmailCode } from '@/services/common/common';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Markdown } from '@repo/ui/markdown'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form'; import { Input } from '@workspace/ui/components/input';
import { Input } from '@shadcn/ui/input'; import { Markdown } from '@workspace/ui/custom-components/markdown';
import { useForm } from '@shadcn/ui/lib/react-hook-form';
import { z, zodResolver } from '@shadcn/ui/lib/zod';
import { useCountDown } from 'ahooks'; import { useCountDown } from 'ahooks';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Dispatch, SetStateAction, useState } from 'react'; import { Dispatch, SetStateAction, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import CloudFlareTurnstile from './turnstile'; import CloudFlareTurnstile from './turnstile';
export default function UserRegisterForm({ export default function UserRegisterForm({

View File

@ -1,14 +1,15 @@
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { sendEmailCode } from '@/services/common/common'; import { sendEmailCode } from '@/services/common/common';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@shadcn/ui/form'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form';
import { Input } from '@shadcn/ui/input'; import { Input } from '@workspace/ui/components/input';
import { useForm } from '@shadcn/ui/lib/react-hook-form';
import { z, zodResolver } from '@shadcn/ui/lib/zod';
import { useCountDown } from 'ahooks'; import { useCountDown } from 'ahooks';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Dispatch, SetStateAction, useState } from 'react'; import { Dispatch, SetStateAction, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import CloudFlareTurnstile from './turnstile'; import CloudFlareTurnstile from './turnstile';
export default function UserResetForm({ export default function UserResetForm({

View File

@ -1,11 +1,16 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { MarkdownEditor } from '@repo/ui/editor'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import {
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; Form,
import { Input } from '@shadcn/ui/input'; FormControl,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormField,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormItem,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { Input } from '@workspace/ui/components/input';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -13,9 +18,12 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { MarkdownEditor } from '@workspace/ui/custom-components/editor';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({ const formSchema = z.object({
title: z.string(), title: z.string(),

View File

@ -1,20 +1,19 @@
'use client'; 'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { import {
createAnnouncement, createAnnouncement,
deleteAnnouncement, deleteAnnouncement,
getAnnouncementList, getAnnouncementList,
updateAnnouncement, updateAnnouncement,
} from '@/services/admin/announcement'; } from '@/services/admin/announcement';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { Button } from '@workspace/ui/components/button';
import { format } from '@shadcn/ui/lib/date-fns'; import { Switch } from '@workspace/ui/components/switch';
import { toast } from '@shadcn/ui/lib/sonner'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { Switch } from '@shadcn/ui/switch'; import { format } from 'date-fns';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { Button } from '@shadcn/ui/button';
import NoticeForm from './notice-form'; import NoticeForm from './notice-form';
export default function Page() { export default function Page() {

View File

@ -1,17 +1,20 @@
'use client'; 'use client';
import { getSubscribeList } from '@/services/admin/subscribe'; import { getSubscribeList } from '@/services/admin/subscribe';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Combobox } from '@repo/ui/combobox'; import { useQuery } from '@tanstack/react-query';
import { DatePicker } from '@repo/ui/date-picker'; import { Button } from '@workspace/ui/components/button';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import {
import { unitConversion } from '@repo/ui/utils'; Form,
import { Button } from '@shadcn/ui/button'; FormControl,
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; FormField,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormItem,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormLabel,
import { RadioGroup, RadioGroupItem } from '@shadcn/ui/radio-group'; FormMessage,
import { ScrollArea } from '@shadcn/ui/scroll-area'; } from '@workspace/ui/components/form';
import { RadioGroup, RadioGroupItem } from '@workspace/ui/components/radio-group';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -19,10 +22,15 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { useQuery } from '@tanstack/react-query'; import { Combobox } from '@workspace/ui/custom-components/combobox';
import { DatePicker } from '@workspace/ui/custom-components/date-picker';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({ const formSchema = z.object({
name: z.string(), name: z.string(),

View File

@ -10,15 +10,15 @@ import {
updateCoupon, updateCoupon,
} from '@/services/admin/coupon'; } from '@/services/admin/coupon';
import { getSubscribeList } from '@/services/admin/subscribe'; import { getSubscribeList } from '@/services/admin/subscribe';
import { ConfirmButton } from '@repo/ui/confirm-button';
import { formatDate } from '@repo/ui/utils';
import { Badge } from '@shadcn/ui/badge';
import { Button } from '@shadcn/ui/button';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch';
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import CouponForm from './coupon-form'; import CouponForm from './coupon-form';
export default function Page() { export default function Page() {

View File

@ -1,12 +1,16 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { MarkdownEditor } from '@repo/ui/editor'; import { Button } from '@workspace/ui/components/button';
import { TagInput } from '@repo/ui/tag-input'; import {
import { Button } from '@shadcn/ui/button'; Form,
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; FormControl,
import { Input } from '@shadcn/ui/input'; FormField,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormItem,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormLabel,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormMessage,
} from '@workspace/ui/components/form';
import { Input } from '@workspace/ui/components/input';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -14,9 +18,13 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { MarkdownEditor } from '@workspace/ui/custom-components/editor';
import { TagInput } from '@workspace/ui/custom-components/tag-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({ const formSchema = z.object({
title: z.string(), title: z.string(),

View File

@ -8,13 +8,13 @@ import {
getDocumentList, getDocumentList,
updateDocument, updateDocument,
} from '@/services/admin/document'; } from '@/services/admin/document';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { Button } from '@workspace/ui/components/button';
import { formatDate } from '@repo/ui/utils'; import { Switch } from '@workspace/ui/components/switch';
import { Button } from '@shadcn/ui/button'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { toast } from '@shadcn/ui/lib/sonner'; import { formatDate } from '@workspace/ui/utils';
import { Switch } from '@shadcn/ui/switch';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import DocumentForm from './document-form'; import DocumentForm from './document-form';
export default function Page() { export default function Page() {

View File

@ -1,6 +1,6 @@
import { Header } from '@/components/header'; import { Header } from '@/components/header';
import { SidebarLeft } from '@/components/sidebar-left'; import { SidebarLeft } from '@/components/sidebar-left';
import { SidebarInset, SidebarProvider } from '@shadcn/ui/sidebar'; import { SidebarInset, SidebarProvider } from '@workspace/ui/components/sidebar';
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
export default async function DashboardLayout({ children }: { children: React.ReactNode }) { export default async function DashboardLayout({ children }: { children: React.ReactNode }) {

View File

@ -8,13 +8,13 @@ import { Display } from '@/components/display';
import { ProTable, ProTableActions } from '@/components/pro-table'; import { ProTable, ProTableActions } from '@/components/pro-table';
import { getOrderList, updateOrderStatus } from '@/services/admin/order'; import { getOrderList, updateOrderStatus } from '@/services/admin/order';
import { getSubscribeList } from '@/services/admin/subscribe'; import { getSubscribeList } from '@/services/admin/subscribe';
import { Combobox } from '@repo/ui/combobox'; import { Badge } from '@workspace/ui/components/badge';
import { formatDate } from '@repo/ui/utils'; import { Button } from '@workspace/ui/components/button';
import { Badge } from '@shadcn/ui/badge'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card';
import { Button } from '@shadcn/ui/button'; import { Separator } from '@workspace/ui/components/separator';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@shadcn/ui/hover-card'; import { Combobox } from '@workspace/ui/custom-components/combobox';
import { cn } from '@shadcn/ui/lib/utils'; import { cn } from '@workspace/ui/lib/utils';
import { Separator } from '@shadcn/ui/separator'; import { formatDate } from '@workspace/ui/utils';
import { UserDetail } from '../user/user-detail'; import { UserDetail } from '../user/user-detail';
export default function Page() { export default function Page() {

View File

@ -1,10 +1,8 @@
'use client'; 'use client';
import { getAlipayF2FPaymentConfig, updateAlipayF2FPaymentConfig } from '@/services/admin/payment'; import { getAlipayF2FPaymentConfig, updateAlipayF2FPaymentConfig } from '@/services/admin/payment';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { useQuery } from '@tanstack/react-query';
import { unitConversion } from '@repo/ui/utils'; import { Label } from '@workspace/ui/components/label';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -12,12 +10,14 @@ import {
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@shadcn/ui/select'; } from '@workspace/ui/components/select';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table'; import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { Textarea } from '@shadcn/ui/textarea'; import { Textarea } from '@workspace/ui/components/textarea';
import { useQuery } from '@tanstack/react-query'; import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function AlipayF2F() { export default function AlipayF2F() {
const t = useTranslations('payment'); const t = useTranslations('payment');

View File

@ -1,10 +1,8 @@
'use client'; 'use client';
import { getEpayPaymentConfig, updateEpayPaymentConfig } from '@/services/admin/payment'; import { getEpayPaymentConfig, updateEpayPaymentConfig } from '@/services/admin/payment';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { useQuery } from '@tanstack/react-query';
import { unitConversion } from '@repo/ui/utils'; import { Label } from '@workspace/ui/components/label';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -12,11 +10,13 @@ import {
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@shadcn/ui/select'; } from '@workspace/ui/components/select';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table'; import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { useQuery } from '@tanstack/react-query'; import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Epay() { export default function Epay() {
const t = useTranslations('payment'); const t = useTranslations('payment');

View File

@ -1,5 +1,5 @@
import Billing from '@/components/billing'; import Billing from '@/components/billing';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import AlipayF2F from './alipayf2f'; import AlipayF2F from './alipayf2f';
import Epay from './epay'; import Epay from './epay';
import StripeAlipay from './stripe-alipay'; import StripeAlipay from './stripe-alipay';

View File

@ -4,10 +4,8 @@ import {
getStripeAlipayPaymentConfig, getStripeAlipayPaymentConfig,
updateStripeAlipayPaymentConfig, updateStripeAlipayPaymentConfig,
} from '@/services/admin/payment'; } from '@/services/admin/payment';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { useQuery } from '@tanstack/react-query';
import { unitConversion } from '@repo/ui/utils'; import { Label } from '@workspace/ui/components/label';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -15,11 +13,13 @@ import {
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@shadcn/ui/select'; } from '@workspace/ui/components/select';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table'; import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { useQuery } from '@tanstack/react-query'; import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Stripe() { export default function Stripe() {
const t = useTranslations('payment'); const t = useTranslations('payment');

View File

@ -4,10 +4,8 @@ import {
getStripeWeChatPayPaymentConfig, getStripeWeChatPayPaymentConfig,
updateStripeWeChatPayPaymentConfig, updateStripeWeChatPayPaymentConfig,
} from '@/services/admin/payment'; } from '@/services/admin/payment';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { useQuery } from '@tanstack/react-query';
import { unitConversion } from '@repo/ui/utils'; import { Label } from '@workspace/ui/components/label';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -15,11 +13,13 @@ import {
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@shadcn/ui/select'; } from '@workspace/ui/components/select';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table'; import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { useQuery } from '@tanstack/react-query'; import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function StripeWeChatPay() { export default function StripeWeChatPay() {
const t = useTranslations('payment'); const t = useTranslations('payment');

View File

@ -1,4 +1,4 @@
import { z } from '@shadcn/ui/lib/zod'; import { z } from 'zod';
export const protocols = ['shadowsocks', 'vmess', 'vless', 'trojan', 'hysteria2', 'tuic']; export const protocols = ['shadowsocks', 'vmess', 'vless', 'trojan', 'hysteria2', 'tuic'];

View File

@ -1,12 +1,17 @@
'use client'; 'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import {
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; Form,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormControl,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormField,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -14,9 +19,12 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({ const formSchema = z.object({
name: z.string(), name: z.string(),

View File

@ -8,12 +8,12 @@ import {
getNodeGroupList, getNodeGroupList,
updateNodeGroup, updateNodeGroup,
} from '@/services/admin/server'; } from '@/services/admin/server';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { Button } from '@workspace/ui/components/button';
import { formatDate } from '@repo/ui/utils'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { Button } from '@shadcn/ui/button'; import { formatDate } from '@workspace/ui/utils';
import { toast } from '@shadcn/ui/lib/sonner';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import GroupForm from './group-form'; import GroupForm from './group-form';
export default function GroupTable() { export default function GroupTable() {

View File

@ -1,18 +1,27 @@
'use client'; 'use client';
import { getNodeGroupList } from '@/services/admin/server'; import { getNodeGroupList } from '@/services/admin/server';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Combobox } from '@repo/ui/combobox'; import { useQuery } from '@tanstack/react-query';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { Button } from '@workspace/ui/components/button';
import { unitConversion } from '@repo/ui/utils'; import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { Button } from '@shadcn/ui/button'; import {
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card'; Form,
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; FormControl,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormField,
import { cn } from '@shadcn/ui/lib/utils'; FormItem,
import { zodResolver } from '@shadcn/ui/lib/zod'; FormLabel,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormMessage,
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select'; } from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@workspace/ui/components/select';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -20,12 +29,16 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { useQuery } from '@tanstack/react-query'; import { Combobox } from '@workspace/ui/custom-components/combobox';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { cn } from '@workspace/ui/lib/utils';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { formSchema, protocols } from './form-schema'; import { formSchema, protocols } from './form-schema';
interface NodeFormProps<T> { interface NodeFormProps<T> {

View File

@ -1,10 +1,15 @@
'use client'; 'use client';
import { formatDate } from '@repo/ui/utils'; import { Badge } from '@workspace/ui/components/badge';
import { Badge } from '@shadcn/ui/badge'; import { Progress } from '@workspace/ui/components/progress';
import { Progress } from '@shadcn/ui/progress'; import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { ScrollArea } from '@shadcn/ui/scroll-area'; import {
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@shadcn/ui/tooltip'; Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@workspace/ui/components/tooltip';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
export function formatPercentage(value: number): string { export function formatPercentage(value: number): string {

View File

@ -11,16 +11,21 @@ import {
nodeSort, nodeSort,
updateNode, updateNode,
} from '@/services/admin/server'; } from '@/services/admin/server';
import { ConfirmButton } from '@repo/ui/confirm-button';
import { Badge } from '@shadcn/ui/badge';
import { Button } from '@shadcn/ui/button';
import { toast } from '@shadcn/ui/lib/sonner';
import { cn } from '@shadcn/ui/lib/utils';
import { Switch } from '@shadcn/ui/switch';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@shadcn/ui/tooltip';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@workspace/ui/components/tooltip';
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { cn } from '@workspace/ui/lib/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import NodeForm from './node-form'; import NodeForm from './node-form';
import { NodeStatusCell } from './node-status'; import { NodeStatusCell } from './node-status';

View File

@ -1,4 +1,4 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
import GroupTable from './group-table'; import GroupTable from './group-table';

View File

@ -1,10 +1,15 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import {
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; Form,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormControl,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormField,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -12,9 +17,12 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({ const formSchema = z.object({
name: z.string(), name: z.string(),

View File

@ -8,12 +8,12 @@ import {
getSubscribeGroupList, getSubscribeGroupList,
updateSubscribeGroup, updateSubscribeGroup,
} from '@/services/admin/subscribe'; } from '@/services/admin/subscribe';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { Button } from '@workspace/ui/components/button';
import { formatDate } from '@repo/ui/utils'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { Button } from '@shadcn/ui/button'; import { formatDate } from '@workspace/ui/utils';
import { toast } from '@shadcn/ui/lib/sonner';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import GroupForm from './group-form'; import GroupForm from './group-form';
const GroupTable = () => { const GroupTable = () => {

View File

@ -1,6 +1,6 @@
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import GroupTable from './group-table'; import GroupTable from './group-table';
import SubscribeTable from './subscribe-table'; import SubscribeTable from './subscribe-table';

View File

@ -1,14 +1,16 @@
import { getNodeGroupList, getNodeList } from '@/services/admin/server'; import { getNodeGroupList, getNodeList } from '@/services/admin/server';
import { getSubscribeGroupList } from '@/services/admin/subscribe'; import { getSubscribeGroupList } from '@/services/admin/subscribe';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { Combobox } from '@repo/ui/combobox'; import { useQuery } from '@tanstack/react-query';
import { ArrayInput } from '@repo/ui/dynamic-Inputs'; import {
import { JSONEditor } from '@repo/ui/editor'; Accordion,
import { EnhancedInput } from '@repo/ui/enhanced-input'; AccordionContent,
import { evaluateWithPrecision, unitConversion } from '@repo/ui/utils'; AccordionItem,
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@shadcn/ui/accordion'; AccordionTrigger,
import { Button } from '@shadcn/ui/button'; } from '@workspace/ui/components/accordion';
import { Checkbox } from '@shadcn/ui/checkbox'; import { Button } from '@workspace/ui/components/button';
import { Checkbox } from '@workspace/ui/components/checkbox';
import { import {
Form, Form,
FormControl, FormControl,
@ -17,11 +19,9 @@ import {
FormItem, FormItem,
FormLabel, FormLabel,
FormMessage, FormMessage,
} from '@shadcn/ui/form'; } from '@workspace/ui/components/form';
import { Label } from '@shadcn/ui/label'; import { Label } from '@workspace/ui/components/label';
import { useForm } from '@shadcn/ui/lib/react-hook-form'; import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { z, zodResolver } from '@shadcn/ui/lib/zod';
import { ScrollArea } from '@shadcn/ui/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -29,11 +29,17 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { useQuery } from '@tanstack/react-query'; import { Combobox } from '@workspace/ui/custom-components/combobox';
import { ArrayInput } from '@workspace/ui/custom-components/dynamic-Inputs';
import { JSONEditor } from '@workspace/ui/custom-components/editor';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { evaluateWithPrecision, unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { assign, shake } from 'radash'; import { assign, shake } from 'radash';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
interface SubscribeFormProps<T> { interface SubscribeFormProps<T> {
onSubmit: (data: T) => Promise<boolean> | boolean; onSubmit: (data: T) => Promise<boolean> | boolean;

View File

@ -11,14 +11,14 @@ import {
subscribeSort, subscribeSort,
updateSubscribe, updateSubscribe,
} from '@/services/admin/subscribe'; } from '@/services/admin/subscribe';
import { ConfirmButton } from '@repo/ui/confirm-button';
import { Badge } from '@shadcn/ui/badge';
import { Button } from '@shadcn/ui/button';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch';
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import SubscribeForm from './subscribe-form'; import SubscribeForm from './subscribe-form';
export default function SubscribeTable() { export default function SubscribeTable() {

View File

@ -1,12 +1,12 @@
'use client'; 'use client';
import { getCurrencyConfig, updateCurrencyConfig } from '@/services/admin/system'; import { getCurrencyConfig, updateCurrencyConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Site() { export default function Site() {
const t = useTranslations('system.currency'); const t = useTranslations('system.currency');

View File

@ -1,16 +1,16 @@
'use client'; 'use client';
import { getEmailSmtpConfig, testEmailSmtp, updateEmailSmtpConfig } from '@/services/admin/system'; import { getEmailSmtpConfig, testEmailSmtp, updateEmailSmtpConfig } from '@/services/admin/system';
import { HTMLEditor } from '@repo/ui/editor';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Button } from '@shadcn/ui/button';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { HTMLEditor } from '@workspace/ui/custom-components/editor';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react'; import { useState } from 'react';
import { toast } from 'sonner';
export default function Email() { export default function Email() {
const t = useTranslations('system.email'); const t = useTranslations('system.email');

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import { getInviteConfig, updateInviteConfig } from '@/services/admin/system'; import { getInviteConfig, updateInviteConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Invite() { export default function Invite() {
const t = useTranslations('system.invite'); const t = useTranslations('system.invite');

View File

@ -2,13 +2,13 @@
import { getNodeConfig, updateNodeConfig } from '@/services/admin/system'; import { getNodeConfig, updateNodeConfig } from '@/services/admin/system';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Node() { export default function Node() {
const t = useTranslations('system.node'); const t = useTranslations('system.node');

View File

@ -1,4 +1,4 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
import Currency from './currency'; import Currency from './currency';

View File

@ -1,14 +1,14 @@
'use client'; 'use client';
import { getRegisterConfig, updateRegisterConfig } from '@/services/admin/system'; import { getRegisterConfig, updateRegisterConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { Textarea } from '@shadcn/ui/textarea';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { Textarea } from '@workspace/ui/components/textarea';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Register() { export default function Register() {
const t = useTranslations('system.register'); const t = useTranslations('system.register');

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import { getSiteConfig, updateSiteConfig } from '@/services/admin/system'; import { getSiteConfig, updateSiteConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { Textarea } from '@shadcn/ui/textarea';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { Textarea } from '@workspace/ui/components/textarea';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Site() { export default function Site() {
const t = useTranslations('system.site'); const t = useTranslations('system.site');

View File

@ -1,9 +1,9 @@
'use client'; 'use client';
import { toast } from '@shadcn/ui/lib/sonner';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { toast } from 'sonner';
import { import {
createApplication, createApplication,
@ -14,14 +14,20 @@ import {
updateApplication, updateApplication,
updateSubscribeConfig, updateSubscribeConfig,
} from '@/services/admin/system'; } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import { Label } from '@workspace/ui/components/label';
import { Label } from '@shadcn/ui/label'; import {
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select'; Select,
import { Switch } from '@shadcn/ui/switch'; SelectContent,
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table'; SelectItem,
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; SelectTrigger,
import { Textarea } from '@shadcn/ui/textarea'; SelectValue,
} from '@workspace/ui/components/select';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Textarea } from '@workspace/ui/components/textarea';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
function compareData( function compareData(
originalData: API.ApplicationResponse, originalData: API.ApplicationResponse,
@ -124,7 +130,7 @@ export default function Subscription() {
}, },
}); });
const [app, setApp] = useState<API.ApplicationResponse>(); const [app, setApp] = useState<API.ApplicationResponse>();
const appTypes = Object.keys(apps || {}); const appTypes = Object.keys(apps || {}) as (keyof API.ApplicationResponse)[];
useEffect(() => { useEffect(() => {
if (!app) setApp(apps); if (!app) setApp(apps);
@ -246,7 +252,7 @@ export default function Subscription() {
})} })}
</TabsList> </TabsList>
{appTypes.map((type) => { {appTypes.map((type) => {
const list = (app?.[type] as API.Application[]) || []; const list = (app?.[type] || []) as API.Application[];
const updatedList = (key: string, value: string, index: number) => { const updatedList = (key: string, value: string, index: number) => {
const newList = list.map((item, i) => (i === index ? { ...item, [key]: value } : item)); const newList = list.map((item, i) => (i === index ? { ...item, [key]: value } : item));

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import { getTelegramConfig, updateTelegramConfig } from '@/services/admin/system'; import { getTelegramConfig, updateTelegramConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Telegram() { export default function Telegram() {
const t = useTranslations('system.telegram'); const t = useTranslations('system.telegram');

View File

@ -1,10 +1,10 @@
'use client'; 'use client';
import { getTosConfig, updateTosConfig } from '@/services/admin/system'; import { getTosConfig, updateTosConfig } from '@/services/admin/system';
import { MarkdownEditor } from '@repo/ui/editor';
import { toast } from '@shadcn/ui/lib/sonner';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { MarkdownEditor } from '@workspace/ui/custom-components/editor';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Tos() { export default function Tos() {
const t = useTranslations('system.tos'); const t = useTranslations('system.tos');

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import { getVerifyConfig, updateVerifyConfig } from '@/services/admin/system'; import { getVerifyConfig, updateVerifyConfig } from '@/services/admin/system';
import { EnhancedInput } from '@repo/ui/enhanced-input';
import { Label } from '@shadcn/ui/label';
import { toast } from '@shadcn/ui/lib/sonner';
import { Switch } from '@shadcn/ui/switch';
import { Table, TableBody, TableCell, TableRow } from '@shadcn/ui/table';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
export default function Verify() { export default function Verify() {
const t = useTranslations('system.verify'); const t = useTranslations('system.verify');

View File

@ -8,9 +8,8 @@ import {
updateTicketStatus, updateTicketStatus,
} from '@/services/admin/ticket'; } from '@/services/admin/ticket';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { useQuery } from '@tanstack/react-query';
import { formatDate } from '@repo/ui/utils'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button';
import { import {
Drawer, Drawer,
DrawerContent, DrawerContent,
@ -18,16 +17,17 @@ import {
DrawerFooter, DrawerFooter,
DrawerHeader, DrawerHeader,
DrawerTitle, DrawerTitle,
} from '@shadcn/ui/drawer'; } from '@workspace/ui/components/drawer';
import { Input } from '@shadcn/ui/input'; import { Input } from '@workspace/ui/components/input';
import { Label } from '@shadcn/ui/label'; import { Label } from '@workspace/ui/components/label';
import { toast } from '@shadcn/ui/lib/sonner'; import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { cn } from '@shadcn/ui/lib/utils'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { ScrollArea } from '@shadcn/ui/scroll-area'; import { cn } from '@workspace/ui/lib/utils';
import { useQuery } from '@tanstack/react-query'; import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import NextImage from 'next/legacy/image'; import NextImage from 'next/legacy/image';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { toast } from 'sonner';
import { UserDetail } from '../user/user-detail'; import { UserDetail } from '../user/user-detail';
export default function Page() { export default function Page() {

View File

@ -2,7 +2,13 @@
import { getSystemLog, restartSystem } from '@/services/admin/tool'; import { getSystemLog, restartSystem } from '@/services/admin/tool';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
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 { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@ -13,12 +19,17 @@ import {
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from '@shadcn/ui/alert-dialog'; } from '@workspace/ui/components/alert-dialog';
import { Badge } from '@shadcn/ui/badge'; import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card'; import {
import { ScrollArea } from '@shadcn/ui/scroll-area'; Card,
import { useQuery } from '@tanstack/react-query'; CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@workspace/ui/components/card';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react'; import { useState } from 'react';
@ -31,7 +42,7 @@ const getLogLevelColor = (level: string) => {
return colorMap[level] || 'bg-gray-100 text-gray-800 hover:bg-gray-200'; return colorMap[level] || 'bg-gray-100 text-gray-800 hover:bg-gray-200';
}; };
export default function page() { export default function Page() {
const t = useTranslations('tool'); const t = useTranslations('tool');
const { const {
data: logs, data: logs,
@ -131,7 +142,7 @@ export default function page() {
</div> </div>
) : ( ) : (
<Accordion type='single' collapsible className='w-full'> <Accordion type='single' collapsible className='w-full'>
{logs?.map((log, index) => ( {logs?.map((log: any, index: number) => (
<AccordionItem key={index} value={`item-${index}`} className='px-4'> <AccordionItem key={index} value={`item-${index}`} className='px-4'>
<AccordionTrigger className='hover:no-underline'> <AccordionTrigger className='hover:no-underline'>
<div className='flex w-full flex-col items-start space-y-2 sm:flex-row sm:items-center sm:space-x-4 sm:space-y-0'> <div className='flex w-full flex-col items-start space-y-2 sm:flex-row sm:items-center sm:space-x-4 sm:space-y-0'>

View File

@ -2,13 +2,13 @@
import { ProTable, ProTableActions } from '@/components/pro-table'; import { ProTable, ProTableActions } from '@/components/pro-table';
import { createUser, deleteUser, getUserList, updateUser } from '@/services/admin/user'; import { createUser, deleteUser, getUserList, updateUser } from '@/services/admin/user';
import { ConfirmButton } from '@repo/ui/confirm-button'; import { Button } from '@workspace/ui/components/button';
import { formatDate, unitConversion } from '@repo/ui/utils'; import { Switch } from '@workspace/ui/components/switch';
import { Button } from '@shadcn/ui/button'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { toast } from '@shadcn/ui/lib/sonner'; import { formatDate, unitConversion } from '@workspace/ui/utils';
import { Switch } from '@shadcn/ui/switch';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { toast } from 'sonner';
import { UserDetail } from './user-detail'; import { UserDetail } from './user-detail';
import UserForm from './user-form'; import UserForm from './user-form';
@ -18,7 +18,7 @@ export default function Page() {
const ref = useRef<ProTableActions>(null); const ref = useRef<ProTableActions>(null);
return ( return (
<ProTable<API.User, any> <ProTable<API.User, Record<string, unknown>>
action={ref} action={ref}
header={{ header={{
title: t('userList'), title: t('userList'),

View File

@ -1,10 +1,10 @@
'use client'; 'use client';
import { getUserDetail } from '@/services/admin/user'; import { getUserDetail } from '@/services/admin/user';
import { formatDate, unitConversion } from '@repo/ui/utils';
import { Button } from '@shadcn/ui/button';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@shadcn/ui/hover-card';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card';
import { formatDate, unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react'; import { useState } from 'react';

View File

@ -1,13 +1,17 @@
'use client'; 'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { EnhancedInput } from '@repo/ui/enhanced-input'; import { Button } from '@workspace/ui/components/button';
import { unitConversion } from '@repo/ui/utils'; import {
import { Button } from '@shadcn/ui/button'; Form,
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@shadcn/ui/form'; FormControl,
import { useForm } from '@shadcn/ui/lib/react-hook-form'; FormField,
import { z, zodResolver } from '@shadcn/ui/lib/zod'; FormItem,
import { ScrollArea } from '@shadcn/ui/scroll-area'; FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { import {
Sheet, Sheet,
SheetContent, SheetContent,
@ -15,10 +19,14 @@ import {
SheetHeader, SheetHeader,
SheetTitle, SheetTitle,
SheetTrigger, SheetTrigger,
} from '@shadcn/ui/sheet'; } from '@workspace/ui/components/sheet';
import { Switch } from '@shadcn/ui/switch'; import { Switch } from '@workspace/ui/components/switch';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { unitConversion } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
interface UserFormProps<T> { interface UserFormProps<T> {
onSubmit: (data: T) => Promise<boolean> | boolean; onSubmit: (data: T) => Promise<boolean> | boolean;
@ -68,7 +76,6 @@ export default function UserForm<T extends Record<string, any>>({
<Sheet open={open} onOpenChange={setOpen}> <Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild> <SheetTrigger asChild>
<Button <Button
size='sm'
onClick={() => { onClick={() => {
form.reset(); form.reset();
setOpen(true); setOpen(true);

View File

@ -1,18 +1,28 @@
import Providers from '@/components/providers'; import Providers from '@/components/providers';
import { geistMono, geistSans } from '@/config/fonts';
import { currentUser } from '@/services/admin/user'; import { currentUser } from '@/services/admin/user';
import { getGlobalConfig } from '@/services/common/common'; import { getGlobalConfig } from '@/services/common/common';
import '@shadcn/ui/globals.css'; import { Toaster } from '@workspace/ui/components/sonner';
import { Toaster } from '@shadcn/ui/sonner'; import '@workspace/ui/globals.css';
import { getLangDir } from '@workspace/ui/hooks/use-lang-dir';
import { Metadata, Viewport } from 'next'; import { Metadata, Viewport } from 'next';
import { NextIntlClientProvider } from 'next-intl'; import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getMessages } from 'next-intl/server'; import { getLocale, getMessages } from 'next-intl/server';
import { PublicEnvScript } from 'next-runtime-env'; import { PublicEnvScript } from 'next-runtime-env';
import { unstable_noStore as noStore } from 'next/cache'; import { unstable_noStore as noStore } from 'next/cache';
import { Geist, Geist_Mono } from 'next/font/google';
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
import NextTopLoader from 'nextjs-toploader'; import NextTopLoader from 'nextjs-toploader';
import React from 'react'; 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> { export async function generateMetadata(): Promise<Metadata> {
noStore(); noStore();
@ -24,7 +34,7 @@ export async function generateMetadata(): Promise<Metadata> {
site = config?.site || undefined; site = config?.site || undefined;
}) })
.catch((error) => { .catch((error) => {
console.error('Error fetching global config:', error); console.log('Error fetching global config:', error);
}); });
const defaultMetadata = { const defaultMetadata = {
@ -60,7 +70,11 @@ export const viewport: Viewport = {
], ],
}; };
export default async function RootLayout({ children }: { children: React.ReactNode }) { export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const locale = await getLocale(); const locale = await getLocale();
const messages = await getMessages(); const messages = await getMessages();
@ -69,7 +83,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
try { try {
config = await getGlobalConfig({ skipErrorHandler: true }).then((res) => res.data.data); config = await getGlobalConfig({ skipErrorHandler: true }).then((res) => res.data.data);
} catch (error) { } catch (error) {
/* empty */ console.log('Error fetching global config:', error);
} }
try { try {
@ -78,17 +92,17 @@ export default async function RootLayout({ children }: { children: React.ReactNo
Authorization: (await cookies()).get('Authorization')?.value, Authorization: (await cookies()).get('Authorization')?.value,
}).then((res) => res.data.data); }).then((res) => res.data.data);
} catch (error) { } catch (error) {
/* empty */ console.log('Error fetching current user:', error);
} }
return ( return (
<html suppressHydrationWarning lang={locale} dir={rtlDetect.getLangDir(locale)}> <html suppressHydrationWarning lang={locale} dir={getLangDir(locale)}>
<head> <head>
<PublicEnvScript /> <PublicEnvScript />
</head> </head>
<body <body
suppressHydrationWarning 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}> <NextIntlClientProvider messages={messages}>
<NextTopLoader showSpinner={false} /> <NextTopLoader showSpinner={false} />

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
}

View File

@ -1,5 +1,5 @@
import { Avatar, AvatarFallback, AvatarImage } from '@shadcn/ui/avatar'; import { Avatar, AvatarFallback, AvatarImage } from '@workspace/ui/components/avatar';
import { Card, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card'; import { Card, CardDescription, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
import Link from 'next/link'; import Link from 'next/link';
@ -25,11 +25,12 @@ export default async function Billing({ type }: BillingProps) {
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json(); const data = await response.json();
const now = new Date().getTime(); const now = new Date().getTime();
list = data[type].filter((item) => { list = data[type].filter((item: { expiryDate: string }) => {
const expiryDate = Date.parse(item.expiryDate); const expiryDate = Date.parse(item.expiryDate);
return !isNaN(expiryDate) && expiryDate > now; return !isNaN(expiryDate) && expiryDate > now;
}); });
} catch (error) { } catch (error) {
console.log('Error fetching billing data:', error);
return null; return null;
} }
if (list && list.length === 0) return null; if (list && list.length === 0) return null;

View File

@ -1,15 +1,25 @@
'use client'; 'use client';
import { queryRevenueStatistics } from '@/services/admin/console'; import { queryRevenueStatistics } from '@/services/admin/console';
import { unitConversion } from '@repo/ui/utils'; import { useQuery } from '@tanstack/react-query';
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@shadcn/ui/card'; import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@workspace/ui/components/card';
import { import {
ChartContainer, ChartContainer,
ChartLegend, ChartLegend,
ChartLegendContent, ChartLegendContent,
ChartTooltip, ChartTooltip,
ChartTooltipContent, ChartTooltipContent,
} from '@shadcn/ui/chart'; } from '@workspace/ui/components/chart';
import { Separator } from '@workspace/ui/components/separator';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { unitConversion } from '@workspace/ui/utils';
import { useLocale, useTranslations } from 'next-intl';
import { import {
Area, Area,
AreaChart, AreaChart,
@ -20,11 +30,7 @@ import {
Pie, Pie,
PieChart, PieChart,
XAxis, XAxis,
} from '@shadcn/ui/lib/recharts'; } from 'recharts';
import { Separator } from '@shadcn/ui/separator';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
import { useQuery } from '@tanstack/react-query';
import { useLocale, useTranslations } from 'next-intl';
import { Display } from '../display'; import { Display } from '../display';
import { Empty } from '../empty'; import { Empty } from '../empty';

View File

@ -2,16 +2,22 @@
import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console'; import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { formatBytes } from '@repo/ui/utils';
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card';
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@shadcn/ui/chart';
import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from '@shadcn/ui/lib/recharts';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select';
import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@workspace/ui/components/chart';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@workspace/ui/components/select';
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { formatBytes } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Link from 'next/link'; import Link from 'next/link';
import { useState } from 'react'; import { useState } from 'react';
import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from 'recharts';
import { Empty } from '../empty'; import { Empty } from '../empty';
import { RevenueStatisticsCard } from './revenue-statistics-card'; import { RevenueStatisticsCard } from './revenue-statistics-card';
import { UserStatisticsCard } from './user-statistics-card'; import { UserStatisticsCard } from './user-statistics-card';
@ -65,8 +71,8 @@ export default function Statistics() {
})) || [], })) || [],
}, },
}; };
const currentData =
const currentData = trafficData[dataType][timeFrame]; trafficData[dataType as 'nodes' | 'users'][timeFrame as 'today' | 'yesterday'];
return ( return (
<> <>

View File

@ -1,14 +1,24 @@
'use client'; 'use client';
import { queryUserStatistics } from '@/services/admin/console'; import { queryUserStatistics } from '@/services/admin/console';
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@shadcn/ui/card'; import { useQuery } from '@tanstack/react-query';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@workspace/ui/components/card';
import { import {
ChartContainer, ChartContainer,
ChartLegend, ChartLegend,
ChartLegendContent, ChartLegendContent,
ChartTooltip, ChartTooltip,
ChartTooltipContent, ChartTooltipContent,
} from '@shadcn/ui/chart'; } from '@workspace/ui/components/chart';
import { Separator } from '@workspace/ui/components/separator';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { useLocale, useTranslations } from 'next-intl';
import { import {
Area, Area,
AreaChart, AreaChart,
@ -19,28 +29,9 @@ import {
Pie, Pie,
PieChart, PieChart,
XAxis, XAxis,
} from '@shadcn/ui/lib/recharts'; } from 'recharts';
import { Separator } from '@shadcn/ui/separator';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
import { useQuery } from '@tanstack/react-query';
import { useLocale, useTranslations } from 'next-intl';
import { Empty } from '../empty'; import { Empty } from '../empty';
const UserStatisticsConfig = {
register: {
label: '注册',
color: 'hsl(var(--chart-1))',
},
new_purchase: {
label: '新购',
color: 'hsl(var(--chart-2))',
},
repurchase: {
label: '复购',
color: 'hsl(var(--chart-3))',
},
};
export function UserStatisticsCard() { export function UserStatisticsCard() {
const t = useTranslations('index'); const t = useTranslations('index');

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import useGlobalStore from '@/config/use-global'; 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'; import { useTranslations } from 'next-intl';
type DisplayType = 'currency' | 'traffic' | 'number'; type DisplayType = 'currency' | 'traffic' | 'number';

View File

@ -1,6 +1,6 @@
'use client'; '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 { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';

View File

@ -7,9 +7,9 @@ import {
BreadcrumbList, BreadcrumbList,
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
} from '@shadcn/ui/breadcrumb'; } from '@workspace/ui/components/breadcrumb';
import { Separator } from '@shadcn/ui/separator'; import { Separator } from '@workspace/ui/components/separator';
import { SidebarTrigger } from '@shadcn/ui/sidebar'; import { SidebarTrigger } from '@workspace/ui/components/sidebar';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import { Fragment, useMemo } from 'react'; import { Fragment, useMemo } from 'react';

View File

@ -3,8 +3,14 @@
import { locales } from '@/config/constants'; import { locales } from '@/config/constants';
import { setLocale } from '@/utils/common'; import { setLocale } from '@/utils/common';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { getCountry } from '@repo/ui/utils'; import {
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@shadcn/ui/select'; Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@workspace/ui/components/select';
import { getCountry } from '@workspace/ui/utils';
import { useLocale, useTranslations } from 'next-intl'; import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
@ -21,7 +27,7 @@ export default function LanguageSwitch() {
return ( return (
<Select defaultValue={locale} onValueChange={handleLanguageChange}> <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> <SelectValue>
<div className='flex items-center'> <div className='flex items-center'>
<Icon icon={`flagpack:${country?.alpha2.toLowerCase()}`} className='!size-5' /> <Icon icon={`flagpack:${country?.alpha2.toLowerCase()}`} className='!size-5' />

View File

@ -1,8 +1,8 @@
'use client'; 'use client';
import { ProTable as _ProTable, ProTableProps } from '@repo/ui/pro-table'; import { ProTable as _ProTable, ProTableProps } from '@workspace/ui/custom-components/pro-table';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
export { type ProTableActions } from '@repo/ui/pro-table'; export { type ProTableActions } from '@workspace/ui/custom-components/pro-table';
export function ProTable< export function ProTable<
TData extends Record<string, unknown>, TData extends Record<string, unknown>,

View File

@ -12,7 +12,7 @@ import {
SidebarMenu, SidebarMenu,
SidebarMenuButton, SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
} from '@shadcn/ui/sidebar'; } from '@workspace/ui/components/sidebar';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Image from 'next/legacy/image'; import Image from 'next/legacy/image';
import Link from 'next/link'; import Link from 'next/link';

View File

@ -1,24 +1,25 @@
'use client'; 'use client';
import { MoonIcon, SunIcon } from '@repo/ui/lotties'; import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, 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'; import { useTheme } from 'next-themes';
export default function ThemeSwitch() { export default function ThemeSwitch() {
const { setTheme } = useTheme(); const { setTheme, resolvedTheme } = useTheme();
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant='ghost' size='icon'> <Button variant='ghost' size='icon'>
<MoonIcon className='size-8 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' /> <DotLottieReact data={resolvedTheme === 'dark' ? MoonLottie : SunLottie} autoplay loop />
<SunIcon className='roate-90 absolute size-8 scale-0 transition-all dark:rotate-0 dark:scale-100' />
<span className='sr-only'>Toggle theme</span> <span className='sr-only'>Toggle theme</span>
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>

View File

@ -2,8 +2,8 @@
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { Logout } from '@/utils/common'; import { Logout } from '@/utils/common';
import { Avatar, AvatarFallback, AvatarImage } from '@shadcn/ui/avatar'; import { Avatar, AvatarFallback, AvatarImage } from '@workspace/ui/components/avatar';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -12,7 +12,7 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuShortcut, DropdownMenuShortcut,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@shadcn/ui/dropdown-menu'; } from '@workspace/ui/components/dropdown-menu';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
export function UserNav() { export function UserNav() {

View File

@ -1,9 +1,10 @@
import { env } from 'next-runtime-env'; 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]; export const NEXT_PUBLIC_DEFAULT_LANGUAGE = env('NEXT_PUBLIC_DEFAULT_LANGUAGE') || defaultLocale;
export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL'); export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL');
export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL'); export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL');

Binary file not shown.

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',
});

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} */ /** @type {import("eslint").Linter.Config} */
export default [ export default [

View File

@ -4,7 +4,7 @@ import createNextIntlPlugin from 'next-intl/plugin';
const withNextIntl = createNextIntlPlugin('./locales/request.ts'); const withNextIntl = createNextIntlPlugin('./locales/request.ts');
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
transpilePackages: ['@shadcn/ui', '@repo/ui'], transpilePackages: ['@workspace/ui'],
output: 'standalone', output: 'standalone',
images: { images: {
remotePatterns: [ remotePatterns: [

View File

@ -11,17 +11,15 @@
}, },
"dependencies": { "dependencies": {
"@iconify/react": "^5.1.0", "@iconify/react": "^5.1.0",
"@repo/ui": "workspace:*", "@lottiefiles/dotlottie-react": "^0.12.0",
"@shadcn/ui": "workspace:*", "@tanstack/react-query": "^5.62.10",
"@tanstack/react-query": "^5.62.7", "@tanstack/react-query-next-experimental": "^5.62.10",
"@tanstack/react-query-next-experimental": "^5.62.7", "@workspace/ui": "workspace:*",
"ahooks": "^3.8.4", "ahooks": "^3.8.4",
"axios": "^1.7.9", "axios": "^1.7.9",
"crypto-js": "^4.2.0",
"mathjs": "^14.0.1",
"nanoid": "^5.0.9", "nanoid": "^5.0.9",
"next": "^15.1.0", "next": "^15.1.2",
"next-intl": "^3.26.1", "next-intl": "^3.26.3",
"next-runtime-env": "^3.2.2", "next-runtime-env": "^3.2.2",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",
"nextjs-toploader": "^3.7.15", "nextjs-toploader": "^3.7.15",
@ -29,17 +27,58 @@
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-turnstile": "^1.1.4", "react-turnstile": "^1.1.4",
"rtl-detect": "^1.1.2",
"universal-cookie": "^7.2.2", "universal-cookie": "^7.2.2",
"zustand": "^5.0.2" "zustand": "^5.0.2"
}, },
"devDependencies": { "devDependencies": {
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^19.0.1", "@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2", "@types/react-dom": "^19.0.2",
"@types/rtl-detect": "^1.0.3", "@types/rtl-detect": "^1.0.3",
"@workspace/eslint-config": "workspace:*",
"@workspace/typescript-config": "workspace:*",
"typescript": "^5.7.2" "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"
]
}
} }
} }

View File

@ -1,9 +1 @@
/** @type {import('postcss-load-config').Config} */ export { default } from '@workspace/ui/postcss.config';
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
export default config;

View File

@ -1,14 +1 @@
import sharedConfig from '@shadcn/ui/tailwind.config'; export * from '@workspace/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;

View File

@ -1,17 +1,23 @@
{ {
"compilerOptions": { "compilerOptions": {
"plugins": [{ "name": "next" }], "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"],
} "@workspace/ui/*": ["../../packages/ui/src/*"]
},
"plugins": [
{
"name": "next"
}
]
}, },
"exclude": ["node_modules"], "exclude": ["node_modules"],
"extends": "@repo/typescript-config/nextjs.json", "extends": "@workspace/typescript-config/nextjs.json",
"include": [ "include": [
"next-env.d.ts", "next-env.d.ts",
"next.config.mjs",
"**/*.ts", "**/*.ts",
"**/*.tsx", "**/*.tsx",
"**/*.mjs",
".next/types/**/*.ts", ".next/types/**/*.ts",
"services/**/typings.d.ts" "services/**/typings.d.ts"
] ]

View File

@ -1,5 +1,5 @@
import { locales, NEXT_PUBLIC_DEFAULT_LANGUAGE } from '@/config/constants'; 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'; import Cookies from 'universal-cookie';
const cookies = new Cookies(null, { const cookies = new Cookies(null, {

View File

@ -1,8 +1,8 @@
import { NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SITE_URL } from '@/config/constants'; import { NEXT_PUBLIC_API_URL, NEXT_PUBLIC_SITE_URL } from '@/config/constants';
import { getTranslations } from '@/locales/utils'; import { getTranslations } from '@/locales/utils';
import { isBrowser } from '@repo/ui/utils'; import { isBrowser } from '@workspace/ui/utils';
import { toast } from '@shadcn/ui/lib/sonner';
import requset, { InternalAxiosRequestConfig } from 'axios'; import requset, { InternalAxiosRequestConfig } from 'axios';
import { toast } from 'sonner';
import { getAuthorization, Logout } from './common'; import { getAuthorization, Logout } from './common';
async function handleError(response: any) { async function handleError(response: any) {

40
apps/user/.gitignore vendored
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

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"
]
}

View File

@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# Install dependencies # Install dependencies
pnpm install bun install
# Run the development server # Run the development server
cd apps/user cd apps/user
pnpm dev bun dev
``` ```
Open <http://localhost:3000> with your browser to see the result. Open <http://localhost:3000> with your browser to see the result.

View File

@ -65,11 +65,11 @@ git clone https://github.com/perfect-panel/ppanel-web.git
cd ppanel-web cd ppanel-web
# 安装依赖 # 安装依赖
pnpm install bun install
# 运行开发服务器 # 运行开发服务器
cd apps/user cd apps/user
pnpm dev bun dev
``` ```
在浏览器中打开 <http://localhost:3000> 查看结果。 在浏览器中打开 <http://localhost:3000> 查看结果。

View File

@ -4,14 +4,20 @@ import { Empty } from '@/components/empty';
import { ProList } from '@/components/pro-list'; import { ProList } from '@/components/pro-list';
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { queryUserAffiliate } from '@/services/user/user'; import { queryUserAffiliate } from '@/services/user/user';
import { formatDate } from '@repo/ui/utils'; import { Button } from '@workspace/ui/components/button';
import { Button } from '@shadcn/ui/button'; import {
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@shadcn/ui/card'; Card,
import { toast } from '@shadcn/ui/lib/sonner'; CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@workspace/ui/components/card';
import { formatDate } from '@workspace/ui/utils';
import { Copy } from 'lucide-react'; import { Copy } from 'lucide-react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react'; import { useState } from 'react';
import { CopyToClipboard } from 'react-copy-to-clipboard'; import { CopyToClipboard } from 'react-copy-to-clipboard';
import { toast } from 'sonner';
export default function Page() { export default function Page() {
const t = useTranslations('affiliate'); const t = useTranslations('affiliate');

View File

@ -2,9 +2,9 @@
import { Empty } from '@/components/empty'; import { Empty } from '@/components/empty';
import { queryAnnouncement } from '@/services/user/announcement'; 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 { useQuery } from '@tanstack/react-query';
import { Timeline } from '@workspace/ui/components/timeline';
import { Markdown } from '@workspace/ui/custom-components/markdown';
export default function Page() { export default function Page() {
const { data } = useQuery({ const { data } = useQuery({

View File

@ -4,8 +4,13 @@ import { Display } from '@/components/display';
import { queryApplicationConfig } from '@/services/user/subscribe'; import { queryApplicationConfig } from '@/services/user/subscribe';
import { queryUserSubscribe } from '@/services/user/user'; import { queryUserSubscribe } from '@/services/user/user';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { getNextResetDate, isBrowser } from '@repo/ui/utils'; import { useQuery } from '@tanstack/react-query';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@shadcn/ui/accordion'; import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@workspace/ui/components/accordion';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@ -16,19 +21,19 @@ import {
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from '@shadcn/ui/alert-dialog'; } from '@workspace/ui/components/alert-dialog';
import { Button } from '@shadcn/ui/button'; import { Button } from '@workspace/ui/components/button';
import { Card, CardContent, CardHeader, CardTitle } from '@shadcn/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { differenceInDays } from '@shadcn/ui/lib/date-fns'; import { Separator } from '@workspace/ui/components/separator';
import { toast } from '@shadcn/ui/lib/sonner'; import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Separator } from '@shadcn/ui/separator'; import { getNextResetDate, isBrowser } from '@workspace/ui/utils';
import { Tabs, TabsList, TabsTrigger } from '@shadcn/ui/tabs'; import { differenceInDays } from 'date-fns';
import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import { QRCodeCanvas } from 'qrcode.react'; import { QRCodeCanvas } from 'qrcode.react';
import { useState } from 'react'; import { useState } from 'react';
import { toast } from 'sonner';
import useGlobalStore from '@/config/use-global'; import useGlobalStore from '@/config/use-global';
import { getStat } from '@/services/common/common'; import { getStat } from '@/services/common/common';

View File

@ -1,13 +1,13 @@
'use client'; 'use client';
import { queryDocumentDetail } from '@/services/user/document'; 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 { 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 { AnimatePresence, motion } from 'framer-motion';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { RefObject, useEffect, useId, useRef, useState } from 'react'; import { RefObject, useEffect, useId, useRef, useState } from 'react';

View File

@ -2,8 +2,8 @@
import { queryDocumentList } from '@/services/user/document'; import { queryDocumentList } from '@/services/user/document';
import { getTutorialList } from '@/utils/tutorial'; import { getTutorialList } from '@/utils/tutorial';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@shadcn/ui/tabs';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { useLocale, useTranslations } from 'next-intl'; import { useLocale, useTranslations } from 'next-intl';
import { DocumentButton } from './document-button'; import { DocumentButton } from './document-button';
import { TutorialButton } from './tutorial-button'; import { TutorialButton } from './tutorial-button';

View File

@ -1,12 +1,12 @@
'use client'; 'use client';
import { getTutorial } from '@/utils/tutorial'; 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 { 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 { AnimatePresence, motion } from 'framer-motion';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { RefObject, useEffect, useId, useRef, useState } from 'react'; import { RefObject, useEffect, useId, useRef, useState } from 'react';

View File

@ -1,5 +1,5 @@
import Announcement from '@/components/announcement'; 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 { cookies } from 'next/headers';
import { SidebarLeft } from './sidebar-left'; import { SidebarLeft } from './sidebar-left';
import { SidebarRight } from './sidebar-right'; import { SidebarRight } from './sidebar-right';

Some files were not shown because too many files have changed in this diff Show More