From d6fbc38795a6dccf5e103040d8bded4b0cd62a58 Mon Sep 17 00:00:00 2001 From: "web@ppanel" Date: Sat, 18 Jan 2025 17:39:26 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(deps):=20Remove=20outdated?= =?UTF-8?q?=20@iconify/react=20dependency=20and=20add=20iconify-json=20pac?= =?UTF-8?q?kages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/app/(auth)/email/login-form.tsx | 9 +- apps/admin/app/(auth)/email/register-form.tsx | 17 +-- apps/admin/app/(auth)/email/reset-form.tsx | 10 +- .../dashboard/announcement/notice-form.tsx | 2 +- .../app/dashboard/coupon/coupon-form.tsx | 2 +- .../app/dashboard/document/document-form.tsx | 2 +- .../admin/app/dashboard/server/group-form.tsx | 2 +- apps/admin/app/dashboard/server/node-form.tsx | 2 +- apps/admin/app/dashboard/ticket/page.tsx | 2 +- apps/admin/app/dashboard/tool/page.tsx | 2 +- apps/admin/app/dashboard/user/user-form.tsx | 2 +- .../admin/components/dashboard/statistics.tsx | 2 +- apps/admin/components/language-switch.tsx | 2 +- apps/admin/components/sidebar-left.tsx | 2 +- apps/admin/locales/cs-CZ/subscribe.json | 21 ++- apps/admin/locales/de-DE/subscribe.json | 21 ++- apps/admin/locales/en-US/subscribe.json | 25 +++- apps/admin/locales/es-ES/subscribe.json | 21 ++- apps/admin/locales/es-MX/subscribe.json | 21 ++- apps/admin/locales/fa-IR/subscribe.json | 21 ++- apps/admin/locales/fi-FI/subscribe.json | 21 ++- apps/admin/locales/fr-FR/subscribe.json | 21 ++- apps/admin/locales/hi-IN/subscribe.json | 21 ++- apps/admin/locales/hu-HU/subscribe.json | 21 ++- apps/admin/locales/ja-JP/subscribe.json | 21 ++- apps/admin/locales/ko-KR/subscribe.json | 21 ++- apps/admin/locales/no-NO/subscribe.json | 21 ++- apps/admin/locales/pl-PL/subscribe.json | 21 ++- apps/admin/locales/pt-BR/subscribe.json | 21 ++- apps/admin/locales/ro-RO/subscribe.json | 21 ++- apps/admin/locales/ru-RU/subscribe.json | 21 ++- apps/admin/locales/th-TH/subscribe.json | 21 ++- apps/admin/locales/tr-TR/subscribe.json | 21 ++- apps/admin/locales/uk-UA/subscribe.json | 21 ++- apps/admin/locales/vi-VN/subscribe.json | 21 ++- apps/admin/locales/zh-CN/subscribe.json | 21 ++- apps/admin/locales/zh-HK/subscribe.json | 21 ++- apps/admin/package.json | 1 - apps/admin/services/admin/app.ts | 101 ++++++++++++++ apps/admin/services/admin/index.ts | 2 + apps/admin/services/admin/system.ts | 45 ++++++ apps/admin/services/admin/typings.d.ts | 128 ++++++++++++++++-- apps/admin/services/common/common.ts | 8 ++ apps/admin/services/common/typings.d.ts | 61 +++++++-- .../app/(main)/(user)/dashboard/content.tsx | 2 +- apps/user/app/(main)/(user)/payment/page.tsx | 2 +- apps/user/app/(main)/(user)/sidebar-left.tsx | 2 +- apps/user/app/(main)/(user)/sidebar-right.tsx | 2 +- .../user/app/(main)/(user)/subscribe/page.tsx | 2 +- apps/user/app/(main)/(user)/ticket/page.tsx | 2 +- apps/user/app/auth/email/login-form.tsx | 9 +- apps/user/app/auth/email/register-form.tsx | 9 +- apps/user/app/auth/email/reset-form.tsx | 9 +- apps/user/app/auth/phone/login-form.tsx | 3 +- apps/user/app/auth/phone/register-form.tsx | 9 +- apps/user/app/auth/phone/reset-form.tsx | 10 +- apps/user/components/announcement/index.tsx | 2 +- apps/user/components/footer.tsx | 2 +- apps/user/components/language-switch.tsx | 2 +- .../user/components/main/product-showcase.tsx | 2 +- apps/user/components/user-nav.tsx | 2 +- apps/user/package.json | 1 - apps/user/services/common/common.ts | 8 ++ apps/user/services/common/typings.d.ts | 61 +++++++-- apps/user/services/user/typings.d.ts | 56 ++++++-- bun.lockb | Bin 608128 -> 609296 bytes packages/ui/package.json | 4 + .../custom-components/area-code-select.tsx | 2 +- .../src/custom-components/dynamic-Inputs.tsx | 75 ++++++---- packages/ui/src/custom-components/icon.tsx | 15 ++ .../ui/src/custom-components/upload-image.tsx | 99 ++++++++++++++ 71 files changed, 1056 insertions(+), 227 deletions(-) create mode 100644 apps/admin/services/admin/app.ts create mode 100644 packages/ui/src/custom-components/icon.tsx create mode 100644 packages/ui/src/custom-components/upload-image.tsx diff --git a/apps/admin/app/(auth)/email/login-form.tsx b/apps/admin/app/(auth)/email/login-form.tsx index 939dd46..fd510df 100644 --- a/apps/admin/app/(auth)/email/login-form.tsx +++ b/apps/admin/app/(auth)/email/login-form.tsx @@ -1,9 +1,9 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction } from 'react'; import { useForm } from 'react-hook-form'; @@ -60,12 +60,7 @@ export default function LoginForm({ render={({ field }) => ( - + diff --git a/apps/admin/app/(auth)/email/register-form.tsx b/apps/admin/app/(auth)/email/register-form.tsx index 7650a15..9ae0c9c 100644 --- a/apps/admin/app/(auth)/email/register-form.tsx +++ b/apps/admin/app/(auth)/email/register-form.tsx @@ -1,9 +1,9 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { Markdown } from '@workspace/ui/custom-components/markdown'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction } from 'react'; @@ -102,12 +102,7 @@ export default function RegisterForm({ render={({ field }) => ( - + @@ -119,12 +114,7 @@ export default function RegisterForm({ render={({ field }) => ( - + @@ -139,7 +129,6 @@ export default function RegisterForm({
( - + @@ -86,7 +81,6 @@ export default function ResetForm({
('/v1/admin/app/config', { + method: 'GET', + ...(options || {}), + }); +} + +/** update app config PUT /v1/admin/app/config */ +export async function updateAppConfig(body: API.AppConfig, options?: { [key: string]: any }) { + return request('/v1/admin/app/config', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** update app version PUT /v1/admin/app/version */ +export async function updateAppVersion( + body: API.UpdateAppVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/app/version', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** create app version POST /v1/admin/app/version */ +export async function createAppVersion( + body: API.CreateAppVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/app/version', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** delete app version DELETE /v1/admin/app/version */ +export async function deleteAppVersionInfo( + body: API.DeleteAppVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/app/version', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** set default app version PUT /v1/admin/app/version_default */ +export async function setDefaultAppVersionInfo( + body: API.DefaultAppVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/app/version_default', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** query app version info GET /v1/admin/app/version_list */ +export async function getAppVersionList( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.GetAppVersionListParams, + options?: { [key: string]: any }, +) { + return request( + '/v1/admin/app/version_list', + { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }, + ); +} diff --git a/apps/admin/services/admin/index.ts b/apps/admin/services/admin/index.ts index 05010d8..057602e 100644 --- a/apps/admin/services/admin/index.ts +++ b/apps/admin/services/admin/index.ts @@ -3,6 +3,7 @@ // API 更新时间: // API 唯一标识: import * as announcement from './announcement'; +import * as app from './app'; import * as console from './console'; import * as coupon from './coupon'; import * as document from './document'; @@ -17,6 +18,7 @@ import * as tool from './tool'; import * as user from './user'; export default { announcement, + app, console, coupon, document, diff --git a/apps/admin/services/admin/system.ts b/apps/admin/services/admin/system.ts index cf52d15..1ab39de 100644 --- a/apps/admin/services/admin/system.ts +++ b/apps/admin/services/admin/system.ts @@ -58,6 +58,51 @@ export async function deleteApplication( }); } +/** Update application version PUT /v1/admin/system/application_version */ +export async function updateApplicationVersion( + body: API.UpdateApplicationVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/system/application_version', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** Create application version POST /v1/admin/system/application_version */ +export async function createApplicationVersion( + body: API.CreateApplicationVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/system/application_version', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** Delete application DELETE /v1/admin/system/application_version */ +export async function deleteApplicationVersion( + body: API.DeleteApplicationVersionRequest, + options?: { [key: string]: any }, +) { + return request('/v1/admin/system/application_version', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + /** Get Currency Config GET /v1/admin/system/currency_config */ export async function getCurrencyConfig(options?: { [key: string]: any }) { return request('/v1/admin/system/currency_config', { diff --git a/apps/admin/services/admin/typings.d.ts b/apps/admin/services/admin/typings.d.ts index 4e704b8..a9d5286 100644 --- a/apps/admin/services/admin/typings.d.ts +++ b/apps/admin/services/admin/typings.d.ts @@ -18,21 +18,59 @@ declare namespace API { updated_at: number; }; + type AppConfig = { + name: string; + domains: string[]; + describe: string; + startup_picture: string; + startup_picture_skip_time: number; + }; + type Application = { id: number; - name: string; - platform: string; - subscribe_type: string; icon: string; - url: string; + name: string; + description: string; + subscribe_type: string; + }; + + type ApplicationPlatform = { + ios?: ApplicationVersion[]; + mac?: ApplicationVersion[]; + linux?: ApplicationVersion[]; + android?: ApplicationVersion[]; + windows?: ApplicationVersion[]; + harmony?: ApplicationVersion[]; }; type ApplicationResponse = { - windows: Application[]; - mac: Application[]; - linux: Application[]; - android: Application[]; - ios: Application[]; + applications: ApplicationResponseInfo[]; + }; + + type ApplicationResponseInfo = { + id: number; + name: string; + icon: string; + description: string; + subscription_protocol: string; + platform: ApplicationPlatform; + }; + + type ApplicationVersion = { + id: number; + url: string; + version: string; + description: string; + is_default: boolean; + }; + + type AppVersion = { + id: number; + os: string; + version: string; + download_url: string; + describe: string; + default_version: boolean; }; type AuthConfig = { @@ -92,11 +130,26 @@ declare namespace API { }; type CreateApplicationRequest = { - name: string; - platform: 'windows' | 'mac' | 'linux' | 'android' | 'ios'; - subscribe_type: string; icon: string; + name: string; + description: string; + subscribe_type: string; + }; + + type CreateApplicationVersionRequest = { url: string; + version: string; + description: string; + platform: 'windows' | 'mac' | 'linux' | 'android' | 'ios' | 'harmony'; + is_default: boolean; + application_id: number; + }; + + type CreateAppVersionRequest = { + os: string; + version: string; + download_url: string; + describe: string; }; type CreateCouponRequest = { @@ -214,6 +267,10 @@ declare namespace API { currency_symbol: string; }; + type DefaultAppVersionRequest = { + id: number; + }; + type DeleteAnnouncementRequest = { id: number; }; @@ -222,6 +279,14 @@ declare namespace API { id: number; }; + type DeleteApplicationVersionRequest = { + id: number; + }; + + type DeleteAppVersionRequest = { + id: number; + }; + type DeleteCouponRequest = { id: number; }; @@ -333,6 +398,23 @@ declare namespace API { id: number; }; + type GetAppVersionListParams = { + page: number; + size: number; + os?: string; + }; + + type GetAppVersionListRequest = { + page: number; + size: number; + os?: string; + }; + + type GetAppVersionListResponse = { + total: number; + list: AppVersion[]; + }; + type GetCouponListParams = { page: number; size: number; @@ -984,10 +1066,28 @@ declare namespace API { type UpdateApplicationRequest = { id: number; - name: string; - subscribe_type: string; icon: string; + name: string; + description: string; + subscribe_type: string; + }; + + type UpdateApplicationVersionRequest = { + id: number; url: string; + version: string; + description: string; + platform: 'windows' | 'mac' | 'linux' | 'android' | 'ios' | 'harmony'; + is_default: boolean; + application_id: number; + }; + + type UpdateAppVersionRequest = { + id: number; + os: string; + version: string; + download_url: string; + describe: string; }; type UpdateCouponRequest = { diff --git a/apps/admin/services/common/common.ts b/apps/admin/services/common/common.ts index 1eda615..b86d7bb 100644 --- a/apps/admin/services/common/common.ts +++ b/apps/admin/services/common/common.ts @@ -2,6 +2,14 @@ /* eslint-disable */ import request from '@/utils/request'; +/** Get Tos Content GET /v1/common/app/info */ +export async function getAppInfo(options?: { [key: string]: any }) { + return request('/v1/common/app/info', { + method: 'GET', + ...(options || {}), + }); +} + /** Get verification code POST /v1/common/send_code */ export async function sendEmailCode(body: API.SendCodeRequest, options?: { [key: string]: any }) { return request('/v1/common/send_code', { diff --git a/apps/admin/services/common/typings.d.ts b/apps/admin/services/common/typings.d.ts index f4ae1dc..29599d5 100644 --- a/apps/admin/services/common/typings.d.ts +++ b/apps/admin/services/common/typings.d.ts @@ -10,21 +10,59 @@ declare namespace API { updated_at: number; }; + type AppConfig = { + name: string; + domains: string[]; + describe: string; + startup_picture: string; + startup_picture_skip_time: number; + }; + type Application = { id: number; - name: string; - platform: string; - subscribe_type: string; icon: string; - url: string; + name: string; + description: string; + subscribe_type: string; + }; + + type ApplicationPlatform = { + ios?: ApplicationVersion[]; + mac?: ApplicationVersion[]; + linux?: ApplicationVersion[]; + android?: ApplicationVersion[]; + windows?: ApplicationVersion[]; + harmony?: ApplicationVersion[]; }; type ApplicationResponse = { - windows: Application[]; - mac: Application[]; - linux: Application[]; - android: Application[]; - ios: Application[]; + applications: ApplicationResponseInfo[]; + }; + + type ApplicationResponseInfo = { + id: number; + name: string; + icon: string; + description: string; + subscription_protocol: string; + platform: ApplicationPlatform; + }; + + type ApplicationVersion = { + id: number; + url: string; + version: string; + description: string; + is_default: boolean; + }; + + type AppVersion = { + id: number; + os: string; + version: string; + download_url: string; + describe: string; + default_version: boolean; }; type AuthConfig = { @@ -113,6 +151,11 @@ declare namespace API { created_at: number; }; + type GetAppInfoResponse = { + config: AppConfig; + versions: AppVersion[]; + }; + type GetGlobalConfigResponse = { site: SiteConfig; verify: VeifyConfig; diff --git a/apps/user/app/(main)/(user)/dashboard/content.tsx b/apps/user/app/(main)/(user)/dashboard/content.tsx index fe318ae..edf27a0 100644 --- a/apps/user/app/(main)/(user)/dashboard/content.tsx +++ b/apps/user/app/(main)/(user)/dashboard/content.tsx @@ -9,7 +9,6 @@ import { getStat } from '@/services/common/common'; import { queryApplicationConfig } from '@/services/user/subscribe'; import { queryUserSubscribe } from '@/services/user/user'; import { getPlatform } from '@/utils/common'; -import { Icon } from '@iconify/react'; import { useQuery } from '@tanstack/react-query'; import { Accordion, @@ -32,6 +31,7 @@ import { Button } from '@workspace/ui/components/button'; import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card'; import { Separator } from '@workspace/ui/components/separator'; import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { isBrowser } from '@workspace/ui/utils'; import { differenceInDays } from 'date-fns'; import { useTranslations } from 'next-intl'; diff --git a/apps/user/app/(main)/(user)/payment/page.tsx b/apps/user/app/(main)/(user)/payment/page.tsx index c4b01ad..5238aaa 100644 --- a/apps/user/app/(main)/(user)/payment/page.tsx +++ b/apps/user/app/(main)/(user)/payment/page.tsx @@ -5,7 +5,6 @@ import { SubscribeBilling } from '@/components/subscribe/billing'; import { SubscribeDetail } from '@/components/subscribe/detail'; import useGlobalStore from '@/config/use-global'; import { checkoutOrder, queryOrderDetail } from '@/services/user/order'; -import { Icon } from '@iconify/react'; import { useQuery } from '@tanstack/react-query'; import { Badge } from '@workspace/ui/components/badge'; import { Button } from '@workspace/ui/components/button'; @@ -17,6 +16,7 @@ import { CardTitle, } from '@workspace/ui/components/card'; import { Separator } from '@workspace/ui/components/separator'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { formatDate } from '@workspace/ui/utils'; import { useCountDown } from 'ahooks'; import { addMinutes, format } from 'date-fns'; diff --git a/apps/user/app/(main)/(user)/sidebar-left.tsx b/apps/user/app/(main)/(user)/sidebar-left.tsx index 17b9802..25a1674 100644 --- a/apps/user/app/(main)/(user)/sidebar-left.tsx +++ b/apps/user/app/(main)/(user)/sidebar-left.tsx @@ -1,6 +1,5 @@ 'use client'; import { navs } from '@/config/navs'; -import { Icon } from '@iconify/react'; import { Sidebar, SidebarContent, @@ -11,6 +10,7 @@ import { SidebarMenuButton, SidebarMenuItem, } from '@workspace/ui/components/sidebar'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; diff --git a/apps/user/app/(main)/(user)/sidebar-right.tsx b/apps/user/app/(main)/(user)/sidebar-right.tsx index f618b5b..f834d00 100644 --- a/apps/user/app/(main)/(user)/sidebar-right.tsx +++ b/apps/user/app/(main)/(user)/sidebar-right.tsx @@ -3,7 +3,6 @@ import { Display } from '@/components/display'; import Recharge from '@/components/subscribe/recharge'; import useGlobalStore from '@/config/use-global'; -import { Icon } from '@iconify/react'; import { Button } from '@workspace/ui/components/button'; import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card'; import { Sidebar, SidebarContent } from '@workspace/ui/components/sidebar'; @@ -13,6 +12,7 @@ import { TooltipProvider, TooltipTrigger, } from '@workspace/ui/components/tooltip'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { isBrowser } from '@workspace/ui/utils'; import { useTranslations } from 'next-intl'; import CopyToClipboard from 'react-copy-to-clipboard'; diff --git a/apps/user/app/(main)/(user)/subscribe/page.tsx b/apps/user/app/(main)/(user)/subscribe/page.tsx index 5000ed3..ff3bd9a 100644 --- a/apps/user/app/(main)/(user)/subscribe/page.tsx +++ b/apps/user/app/(main)/(user)/subscribe/page.tsx @@ -2,12 +2,12 @@ import { Display } from '@/components/display'; import { querySubscribeGroupList, querySubscribeList } from '@/services/user/subscribe'; -import { Icon } from '@iconify/react'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@workspace/ui/components/button'; import { Card, CardContent, CardFooter, CardHeader } from '@workspace/ui/components/card'; import { Separator } from '@workspace/ui/components/separator'; import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { cn } from '@workspace/ui/lib/utils'; import { useTranslations } from 'next-intl'; import { useState } from 'react'; diff --git a/apps/user/app/(main)/(user)/ticket/page.tsx b/apps/user/app/(main)/(user)/ticket/page.tsx index 607e1f4..fe21356 100644 --- a/apps/user/app/(main)/(user)/ticket/page.tsx +++ b/apps/user/app/(main)/(user)/ticket/page.tsx @@ -9,7 +9,6 @@ import { getUserTicketList, updateUserTicketStatus, } from '@/services/user/ticket'; -import { Icon } from '@iconify/react'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@workspace/ui/components/button'; import { @@ -41,6 +40,7 @@ import { Label } from '@workspace/ui/components/label'; import { ScrollArea } from '@workspace/ui/components/scroll-area'; import { Textarea } from '@workspace/ui/components/textarea'; import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { cn } from '@workspace/ui/lib/utils'; import { formatDate } from '@workspace/ui/utils'; import { useTranslations } from 'next-intl'; diff --git a/apps/user/app/auth/email/login-form.tsx b/apps/user/app/auth/email/login-form.tsx index 939dd46..fd510df 100644 --- a/apps/user/app/auth/email/login-form.tsx +++ b/apps/user/app/auth/email/login-form.tsx @@ -1,9 +1,9 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction } from 'react'; import { useForm } from 'react-hook-form'; @@ -60,12 +60,7 @@ export default function LoginForm({ render={({ field }) => ( - + diff --git a/apps/user/app/auth/email/register-form.tsx b/apps/user/app/auth/email/register-form.tsx index 7650a15..821d6c6 100644 --- a/apps/user/app/auth/email/register-form.tsx +++ b/apps/user/app/auth/email/register-form.tsx @@ -1,9 +1,9 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { Markdown } from '@workspace/ui/custom-components/markdown'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction } from 'react'; @@ -102,12 +102,7 @@ export default function RegisterForm({ render={({ field }) => ( - + diff --git a/apps/user/app/auth/email/reset-form.tsx b/apps/user/app/auth/email/reset-form.tsx index 4ae43f0..cf1cc0f 100644 --- a/apps/user/app/auth/email/reset-form.tsx +++ b/apps/user/app/auth/email/reset-form.tsx @@ -1,9 +1,9 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction } from 'react'; import { useForm } from 'react-hook-form'; @@ -65,12 +65,7 @@ export default function ResetForm({ render={({ field }) => ( - + diff --git a/apps/user/app/auth/phone/login-form.tsx b/apps/user/app/auth/phone/login-form.tsx index e1707e8..c06d930 100644 --- a/apps/user/app/auth/phone/login-form.tsx +++ b/apps/user/app/auth/phone/login-form.tsx @@ -1,10 +1,10 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; import { AreaCodeSelect } from '@workspace/ui/custom-components/area-code-select'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction, useState } from 'react'; @@ -99,7 +99,6 @@ export default function LoginForm({
( - + diff --git a/apps/user/app/auth/phone/reset-form.tsx b/apps/user/app/auth/phone/reset-form.tsx index 7882420..6917d96 100644 --- a/apps/user/app/auth/phone/reset-form.tsx +++ b/apps/user/app/auth/phone/reset-form.tsx @@ -1,10 +1,10 @@ import useGlobalStore from '@/config/use-global'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Icon } from '@iconify/react/dist/iconify.js'; import { Button } from '@workspace/ui/components/button'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@workspace/ui/components/form'; import { Input } from '@workspace/ui/components/input'; import { AreaCodeSelect } from '@workspace/ui/custom-components/area-code-select'; +import { Icon } from '@workspace/ui/custom-components/icon'; import { useTranslations } from 'next-intl'; import { Dispatch, SetStateAction, useState } from 'react'; import { useForm } from 'react-hook-form'; @@ -97,12 +97,7 @@ export default function ResetForm({ render={({ field }) => ( - + @@ -118,7 +113,6 @@ export default function ResetForm({
('/v1/common/app/info', { + method: 'GET', + ...(options || {}), + }); +} + /** Get verification code POST /v1/common/send_code */ export async function sendEmailCode(body: API.SendCodeRequest, options?: { [key: string]: any }) { return request('/v1/common/send_code', { diff --git a/apps/user/services/common/typings.d.ts b/apps/user/services/common/typings.d.ts index f4ae1dc..29599d5 100644 --- a/apps/user/services/common/typings.d.ts +++ b/apps/user/services/common/typings.d.ts @@ -10,21 +10,59 @@ declare namespace API { updated_at: number; }; + type AppConfig = { + name: string; + domains: string[]; + describe: string; + startup_picture: string; + startup_picture_skip_time: number; + }; + type Application = { id: number; - name: string; - platform: string; - subscribe_type: string; icon: string; - url: string; + name: string; + description: string; + subscribe_type: string; + }; + + type ApplicationPlatform = { + ios?: ApplicationVersion[]; + mac?: ApplicationVersion[]; + linux?: ApplicationVersion[]; + android?: ApplicationVersion[]; + windows?: ApplicationVersion[]; + harmony?: ApplicationVersion[]; }; type ApplicationResponse = { - windows: Application[]; - mac: Application[]; - linux: Application[]; - android: Application[]; - ios: Application[]; + applications: ApplicationResponseInfo[]; + }; + + type ApplicationResponseInfo = { + id: number; + name: string; + icon: string; + description: string; + subscription_protocol: string; + platform: ApplicationPlatform; + }; + + type ApplicationVersion = { + id: number; + url: string; + version: string; + description: string; + is_default: boolean; + }; + + type AppVersion = { + id: number; + os: string; + version: string; + download_url: string; + describe: string; + default_version: boolean; }; type AuthConfig = { @@ -113,6 +151,11 @@ declare namespace API { created_at: number; }; + type GetAppInfoResponse = { + config: AppConfig; + versions: AppVersion[]; + }; + type GetGlobalConfigResponse = { site: SiteConfig; verify: VeifyConfig; diff --git a/apps/user/services/user/typings.d.ts b/apps/user/services/user/typings.d.ts index d084fec..dd5b479 100644 --- a/apps/user/services/user/typings.d.ts +++ b/apps/user/services/user/typings.d.ts @@ -10,21 +10,59 @@ declare namespace API { updated_at: number; }; + type AppConfig = { + name: string; + domains: string[]; + describe: string; + startup_picture: string; + startup_picture_skip_time: number; + }; + type Application = { id: number; - name: string; - platform: string; - subscribe_type: string; icon: string; - url: string; + name: string; + description: string; + subscribe_type: string; + }; + + type ApplicationPlatform = { + ios?: ApplicationVersion[]; + mac?: ApplicationVersion[]; + linux?: ApplicationVersion[]; + android?: ApplicationVersion[]; + windows?: ApplicationVersion[]; + harmony?: ApplicationVersion[]; }; type ApplicationResponse = { - windows: Application[]; - mac: Application[]; - linux: Application[]; - android: Application[]; - ios: Application[]; + applications: ApplicationResponseInfo[]; + }; + + type ApplicationResponseInfo = { + id: number; + name: string; + icon: string; + description: string; + subscription_protocol: string; + platform: ApplicationPlatform; + }; + + type ApplicationVersion = { + id: number; + url: string; + version: string; + description: string; + is_default: boolean; + }; + + type AppVersion = { + id: number; + os: string; + version: string; + download_url: string; + describe: string; + default_version: boolean; }; type AuthConfig = { diff --git a/bun.lockb b/bun.lockb index 1ef807bf4bf3712b7c52412ef4cf5170dae2abe1..059ed41b6d9e27bf5ddbf0ca1094ff838d3152d1 100755 GIT binary patch delta 42868 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
R5dTe$sjBid9fIvE($T(1JTR} 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 { name: string; - type: 'text' | 'number' | 'select' | 'time'; + type: 'text' | 'number' | 'select' | 'time' | 'boolean'; options?: { label: string; value: string }[]; internal?: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -18,6 +20,7 @@ interface ObjectInputProps { value: T; onChange: (value: T) => void; fields: FieldConfig[]; + className?: string; } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -25,6 +28,7 @@ export function ObjectInput>({ value, onChange, fields, + className, }: ObjectInputProps) { const [internalState, setInternalState] = useState(value); @@ -32,7 +36,7 @@ export function ObjectInput>({ setInternalState(value); }, [value]); - const updateField = (key: keyof T, fieldValue: string | number) => { + const updateField = (key: keyof T, fieldValue: string | number | boolean) => { let updatedInternalState = { ...internalState, [key]: fieldValue }; fields.forEach((field) => { if (field.calculateValue && field.name === key) { @@ -52,28 +56,44 @@ export function ObjectInput>({ onChange(filteredValue); }; - - return ( -
- {fields.map(({ name, type, options, className, ...fieldProps }) => ( -
- {type === 'select' && options ? ( + const renderField = (field: FieldConfig) => { + switch (field.type) { + case 'select': + return ( + field.options && ( - placeholder={fieldProps.placeholder} - options={options} - value={internalState[name]} - onChange={(fieldValue) => { - updateField(name, fieldValue); - }} + placeholder={field.placeholder} + options={field.options} + value={internalState[field.name]} + onChange={(fieldValue) => updateField(field.name, fieldValue)} /> - ) : ( - updateField(name, fieldValue)} - type={type} - {...fieldProps} + ) + ); + case 'boolean': + return ( +
+ updateField(field.name, fieldValue)} /> - )} + {field.placeholder && } +
+ ); + default: + return ( + updateField(field.name, fieldValue)} + {...field} + /> + ); + } + }; + return ( +
+ {fields.map((field) => ( +
+ {renderField(field)}
))}
@@ -83,6 +103,8 @@ interface ArrayInputProps { value?: T[]; onChange: (value: T[]) => void; fields: FieldConfig[]; + isReverse?: boolean; + className?: string; } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -90,6 +112,8 @@ export function ArrayInput>({ value = [], onChange, fields, + isReverse = false, + className, }: ArrayInputProps) { const initializeDefaultItem = (): T => fields.reduce((acc, field) => { @@ -117,7 +141,11 @@ export function ArrayInput>({ }; const createField = () => { - setDisplayItems([...displayItems, initializeDefaultItem()]); + if (isReverse) { + setDisplayItems([initializeDefaultItem(), ...displayItems]); + } else { + setDisplayItems([...displayItems, initializeDefaultItem()]); + } }; const deleteField = (index: number) => { @@ -142,6 +170,7 @@ export function ArrayInput>({ value={item} onChange={(updatedItem) => handleItemChange(index, updatedItem)} fields={fields} + className={className} />
{displayItems.length > 1 && ( @@ -155,7 +184,7 @@ export function ArrayInput>({ )} - {index === displayItems.length - 1 && ( + {(isReverse ? index === 0 : index === displayItems.length - 1) && (