feat: 完成代码编写
This commit is contained in:
parent
2ee4121308
commit
988011191b
@ -27,7 +27,7 @@ export function SidebarLeft({ ...props }: React.ComponentProps<typeof Sidebar>)
|
|||||||
'relative ml-2.5 flex h-[calc(100dvh-10px-env(safe-area-inset-top))] flex-col rounded-[30px] bg-[#D9D9D9] px-4 md:ml-0 md:h-full md:rounded-none md:bg-white'
|
'relative ml-2.5 flex h-[calc(100dvh-10px-env(safe-area-inset-top))] flex-col rounded-[30px] bg-[#D9D9D9] px-4 md:ml-0 md:h-full md:rounded-none md:bg-white'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className={'absolute -right-3 top-6'} onClick={toggleSidebar}>
|
<div className={'absolute -right-3 top-6 md:hidden'} onClick={toggleSidebar}>
|
||||||
<Image src={'shrink.png'} height={30} width={30} alt='close' unoptimized></Image>
|
<Image src={'shrink.png'} height={30} width={30} alt='close' unoptimized></Image>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -92,7 +92,23 @@ export default function Page() {
|
|||||||
value={tabValue}
|
value={tabValue}
|
||||||
onValueChange={(value) => setTabValue(value as 'year' | 'month')}
|
onValueChange={(value) => setTabValue(value as 'year' | 'month')}
|
||||||
>
|
>
|
||||||
<TabsList className='mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
|
<TabsList className='relative mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
|
||||||
|
{tabValue === 'year' ? (
|
||||||
|
<span className='absolute -top-8 left-16 z-10 rounded-md bg-[#E22C2E] px-2 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
|
||||||
|
-20%
|
||||||
|
{/* 小三角箭头 */}
|
||||||
|
{/* <span className="
|
||||||
|
absolute right-0 top-full
|
||||||
|
block h-0 w-0
|
||||||
|
border-l-[6px] border-r-[6px] border-t-[16px]
|
||||||
|
border-l-transparent border-r-transparent border-t-[#E22C2E]
|
||||||
|
" />*/}
|
||||||
|
<span
|
||||||
|
className='absolute right-0 top-[80%] h-10 w-2 bg-[#E22C2E]'
|
||||||
|
style={{ clipPath: 'polygon(100% 0, 100% 100%, 0 0)' }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
className={
|
className={
|
||||||
'rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
'rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
||||||
|
|||||||
@ -115,6 +115,7 @@ export default function LoginForm({
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant='link'
|
variant='link'
|
||||||
|
type='button'
|
||||||
className='p-0 text-[#225BA9]'
|
className='p-0 text-[#225BA9]'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setInitialValues(undefined);
|
setInitialValues(undefined);
|
||||||
|
|||||||
@ -225,6 +225,7 @@ export default function RegisterForm({
|
|||||||
{t('existingAccount')}
|
{t('existingAccount')}
|
||||||
<Button
|
<Button
|
||||||
variant='link'
|
variant='link'
|
||||||
|
type='button'
|
||||||
className='p-0 text-[#225BA9]'
|
className='p-0 text-[#225BA9]'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setInitialValues(undefined);
|
setInitialValues(undefined);
|
||||||
|
|||||||
@ -145,6 +145,7 @@ export default function ResetForm({
|
|||||||
{t('existingAccount')}
|
{t('existingAccount')}
|
||||||
<Button
|
<Button
|
||||||
variant='link'
|
variant='link'
|
||||||
|
type='button'
|
||||||
className='p-0 text-[#225BA9]'
|
className='p-0 text-[#225BA9]'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setInitialValues(undefined);
|
setInitialValues(undefined);
|
||||||
|
|||||||
@ -37,7 +37,7 @@ const languages = {
|
|||||||
'uk-UA': 'Українська',
|
'uk-UA': 'Українська',
|
||||||
'vi-VN': 'Tiếng Việt',
|
'vi-VN': 'Tiếng Việt',
|
||||||
'zh-CN': '简体中文',
|
'zh-CN': '简体中文',
|
||||||
'zh-HK': '繁體中文',
|
// 'zh-HK': '繁體中文',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default function LanguageSwitch() {
|
export default function LanguageSwitch() {
|
||||||
|
|||||||
@ -398,7 +398,23 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
|
|||||||
value={tabValue}
|
value={tabValue}
|
||||||
onValueChange={setTabValue}
|
onValueChange={setTabValue}
|
||||||
>
|
>
|
||||||
<TabsList className='mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
|
<TabsList className='relative mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
|
||||||
|
{tabValue === 'year' ? (
|
||||||
|
<span className='absolute -top-8 left-16 z-10 rounded-md bg-[#E22C2E] px-2 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
|
||||||
|
-20%
|
||||||
|
{/* 小三角箭头 */}
|
||||||
|
{/* <span className="
|
||||||
|
absolute right-0 top-full
|
||||||
|
block h-0 w-0
|
||||||
|
border-l-[6px] border-r-[6px] border-t-[16px]
|
||||||
|
border-l-transparent border-r-transparent border-t-[#E22C2E]
|
||||||
|
" />*/}
|
||||||
|
<span
|
||||||
|
className='absolute right-0 top-[80%] h-10 w-2 bg-[#E22C2E]'
|
||||||
|
style={{ clipPath: 'polygon(100% 0, 100% 100%, 0 0)' }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
className={
|
className={
|
||||||
'rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
'rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
||||||
|
|||||||
@ -139,7 +139,23 @@ const Purchase = forwardRef<PurchaseDialogRef, PurchaseProps>((props, ref) => {
|
|||||||
setTabValue(val);
|
setTabValue(val);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TabsList className='mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5'>
|
<TabsList className='relative mb-8 h-[74px] flex-wrap rounded-full bg-[#EAEAEA] p-2.5'>
|
||||||
|
{tabValue === 'year' ? (
|
||||||
|
<span className='absolute -top-8 left-16 z-10 rounded-md bg-[#E22C2E] px-2 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
|
||||||
|
-20%
|
||||||
|
{/* 小三角箭头 */}
|
||||||
|
{/* <span className="
|
||||||
|
absolute right-0 top-full
|
||||||
|
block h-0 w-0
|
||||||
|
border-l-[6px] border-r-[6px] border-t-[16px]
|
||||||
|
border-l-transparent border-r-transparent border-t-[#E22C2E]
|
||||||
|
" />*/}
|
||||||
|
<span
|
||||||
|
className='absolute right-0 top-[80%] h-10 w-2 bg-[#E22C2E]'
|
||||||
|
style={{ clipPath: 'polygon(100% 0, 100% 100%, 0 0)' }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
className='rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
className='rounded-full px-10 py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
||||||
value='year'
|
value='year'
|
||||||
|
|||||||
@ -57,41 +57,12 @@
|
|||||||
"entryLocale": "en-US",
|
"entryLocale": "en-US",
|
||||||
"output": "./locales",
|
"output": "./locales",
|
||||||
"outputLocales": [
|
"outputLocales": [
|
||||||
"cs-CZ",
|
|
||||||
"de-DE",
|
|
||||||
"en-US",
|
"en-US",
|
||||||
"es-ES",
|
"zh-CN"
|
||||||
"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-mini",
|
"modelName": "gpt-4o-mini",
|
||||||
"experimental": {
|
"experimental": {
|
||||||
"jsonMode": true
|
"jsonMode": true
|
||||||
},
|
|
||||||
"markdown": {
|
|
||||||
"entry": [
|
|
||||||
"./README.md"
|
|
||||||
],
|
|
||||||
"outputLocales": [
|
|
||||||
"zh-CN"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,17 @@ const SIDEBAR_WIDTH_MOBILE = '14rem';
|
|||||||
const SIDEBAR_WIDTH_ICON = '2rem';
|
const SIDEBAR_WIDTH_ICON = '2rem';
|
||||||
const SIDEBAR_KEYBOARD_SHORTCUT = 'b';
|
const SIDEBAR_KEYBOARD_SHORTCUT = 'b';
|
||||||
|
|
||||||
|
// Define a safe default context so consumers won't crash without a Provider
|
||||||
|
const SAFE_SIDEBAR_CONTEXT: SidebarContext = {
|
||||||
|
state: 'collapsed',
|
||||||
|
open: false,
|
||||||
|
setOpen: () => {},
|
||||||
|
openMobile: false,
|
||||||
|
setOpenMobile: () => {},
|
||||||
|
isMobile: false,
|
||||||
|
toggleSidebar: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
type SidebarContext = {
|
type SidebarContext = {
|
||||||
state: 'expanded' | 'collapsed';
|
state: 'expanded' | 'collapsed';
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -36,14 +47,14 @@ type SidebarContext = {
|
|||||||
toggleSidebar: () => void;
|
toggleSidebar: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SidebarContext = React.createContext<SidebarContext | null>(null);
|
const SidebarContext = React.createContext<SidebarContext>(SAFE_SIDEBAR_CONTEXT);
|
||||||
|
|
||||||
function useSidebar() {
|
function useSidebar() {
|
||||||
const context = React.useContext(SidebarContext);
|
const context = React.useContext(SidebarContext);
|
||||||
if (!context) {
|
// Optionally warn in development when using the safe fallback
|
||||||
throw new Error('useSidebar must be used within a SidebarProvider.');
|
if (process.env.NODE_ENV !== 'production' && context === SAFE_SIDEBAR_CONTEXT) {
|
||||||
|
// console.warn('useSidebar is used outside of a SidebarProvider. Falling back to no-op context.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user