-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ee862e3
commit 8edd4e3
Showing
9 changed files
with
266 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { z } from 'zod'; | ||
|
||
export const restartChallengeSchema = z.object({ | ||
userId: z.string().uuid(), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import 'server-only'; | ||
import { NextResponse, type NextRequest } from 'next/server'; | ||
import { restartChallengeSchema } from './restart-challenge-schema'; | ||
import { serverContainer } from '@/services/server/container'; | ||
import { SERVER_SERVICE_KEYS } from '@/services/server/keys'; | ||
import { ServerError } from '@/errors/server-error'; | ||
|
||
export async function PUT(request: NextRequest) { | ||
const auth = serverContainer.get(SERVER_SERVICE_KEYS.Auth); | ||
const userRepository = serverContainer.get(SERVER_SERVICE_KEYS.UserRepository); | ||
|
||
try { | ||
const data = await request.json(); | ||
const { userId } = restartChallengeSchema.parse(data); | ||
|
||
const user = await auth.loadSessionUser(); | ||
// impossible that frontend and cookie issue. | ||
if (!user || user.uid !== userId) { | ||
return NextResponse.json( | ||
{ error: 'Unauthorized' }, | ||
{ status: 401 }, | ||
); | ||
} | ||
//sign in so no issue in the user id . please improve it!!!!!! | ||
const newTimestamp = await userRepository.restartChallenge(userId); | ||
|
||
return NextResponse.json( | ||
{ challengeEndTimestamp: newTimestamp }, | ||
{ status: 200 }, | ||
); | ||
} catch (e) { | ||
if (e instanceof ServerError) { | ||
return NextResponse.json({ error: e.message }, { status: e.statusCode }); | ||
} | ||
|
||
return NextResponse.json({ error: 'Bad data.' }, { status: 400 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// button.module.scss | ||
@use '../../styles/partials/variables/font-families'; | ||
@use '../../styles/partials/variables/font-weights'; | ||
@use '../../styles/partials/variables/letter-spacings'; | ||
@use '../../styles/partials/variables/font-sizes'; | ||
@use '../../styles/partials/variables/colors'; | ||
@use '../../styles/partials/variables/gradients'; | ||
|
||
@mixin -base { | ||
position: relative; | ||
display: inline-block; | ||
font-family: font-families.$bebas-neue; | ||
font-weight: font-weights.$regular; | ||
letter-spacing: letter-spacings.$large; | ||
text-align: center; | ||
text-decoration: none; | ||
text-transform: uppercase; | ||
border-style: solid; | ||
border-radius: 40px; | ||
border-width: 4px; | ||
border-color: colors.$black-8by8; | ||
} | ||
|
||
@mixin -outline { | ||
&::after { | ||
content: ""; | ||
position: absolute; | ||
border-radius: 40px; | ||
top: -8px; | ||
left: -8px; | ||
right: -8px; | ||
bottom: -8px; | ||
border: colors.$white 4px solid; | ||
} | ||
} | ||
|
||
@mixin -gradient-text { | ||
:first-child { | ||
// a span element should be added inside the button to contain the text, these styles will apply to it | ||
background: gradients.$yellow-teal; | ||
background-clip: text; | ||
-webkit-background-clip: text; | ||
-moz-background-clip: text; | ||
-webkit-text-fill-color: transparent; | ||
-moz-text-fill-color: transparent; | ||
color: transparent; | ||
font-size: inherit; | ||
} | ||
} | ||
|
||
.btn_gradient { | ||
@include -base; | ||
@include -outline; | ||
background: gradients.$yellow-teal; | ||
color: colors.$black-8by8; | ||
} | ||
.custom-font-size { | ||
font-size: 20px; // 你可以根据需要调整字体大小 | ||
} | ||
.btn_inverted { | ||
@include -base; | ||
@include -gradient-text; | ||
@include -outline; | ||
background: colors.$black-8by8; | ||
} | ||
|
||
.btn_lg { | ||
font-size: font-sizes.$lg; | ||
height: 64px; | ||
border-radius: 40px; | ||
border-width: 4px; | ||
} | ||
|
||
.btn_sm { | ||
font-size: font-sizes.$md; | ||
padding: 4px 14px; | ||
} | ||
|
||
.btn_wide { | ||
width: 100%; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Button.tsx | ||
import React, { FC } from 'react'; | ||
import styles from './button.module.scss'; | ||
|
||
type ButtonProps = { | ||
variant?: 'btn_gradient' | 'btn_inverted'; | ||
size?: 'btn_lg' | 'btn_sm'; | ||
wide?: boolean; | ||
children: React.ReactNode; | ||
}; | ||
|
||
const Button: FC<ButtonProps> = ({ variant = 'btn_gradient', size = 'btn_lg', wide = false, children }) => { | ||
const classNames = [styles[variant], styles[size]]; | ||
if (wide) { | ||
classNames.push(styles.btn_wide); | ||
} | ||
|
||
console.log('Button classNames:', classNames); // Debugging line | ||
|
||
return ( | ||
<button className={classNames.join(' ')}> | ||
<span>{children}</span> | ||
</button> | ||
); | ||
}; | ||
|
||
export default Button; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as Button } from './button'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"use client"; | ||
import { Modal } from "@/components/utils/modal"; | ||
import { Button } from "@/components/utils/button"; | ||
import { useContextSafely } from "@/hooks/use-context-safely"; | ||
import { UserContext } from "@/contexts/user-context"; | ||
import { calculateDaysRemaining } from "@/app/progress/calculate-days-remaining"; | ||
import { useState } from "react"; | ||
|
||
export function RestartChallengeModal() { | ||
const [isLoading, setLoading] = useState(false); | ||
|
||
const { restartChallenge, user } = useContextSafely(UserContext, "RestartChallengeModal"); | ||
if (!user) return null; | ||
const showModal = calculateDaysRemaining(user) === 0; | ||
const restartAndChangeisLoading = async () => { | ||
try{ | ||
setLoading(true); | ||
await restartChallenge(); | ||
} catch (error) {} | ||
finally { | ||
setLoading(false); | ||
} | ||
} | ||
return ( | ||
<Modal ariaLabel="Restart Challenge" theme="dark" isOpen={showModal} closeModal={() => {}}> | ||
{isLoading ? ( | ||
<p>Restarting your challenge...</p> | ||
) : ( | ||
<> | ||
<p>Oops, times up! But no worries, restart your challenge to continue!</p> | ||
|
||
<Button | ||
onClick={restartAndChangeisLoading} | ||
size="sm" | ||
style={{ marginTop: '16px' }} // 你可以根据需要调整这个值 | ||
> | ||
Restart Challenge | ||
</Button> | ||
</> | ||
)} | ||
</Modal> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
src/stories/components/restart-challenge/restart.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
import { GlobalStylesProvider } from '@/stories/global-styles-provider'; | ||
import { RestartChallengeModal } from '@/contexts/user-context/restart-challenge-modal'; | ||
import { Builder } from 'builder-pattern'; | ||
import { UserContext,type UserContextType } from '@/contexts/user-context'; | ||
import type { User } from '@/model/types/user'; | ||
import { PropsWithChildren, useState } from 'react'; | ||
import { time } from 'console'; | ||
import { promise } from 'zod'; | ||
import { DateTime } from 'luxon'; | ||
const meta: Meta<typeof RestartChallengeModal> = { | ||
component: RestartChallengeModal, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof RestartChallengeModal>; | ||
|
||
const createUserContext = () => { | ||
const user: User = Builder<User>().uid("1").challengeEndTimestamp(0).build(); | ||
}; | ||
function UserContextProvider({ children } : PropsWithChildren) { | ||
const [user, setUser] = useState<User>(Builder<User>().uid("1").challengeEndTimestamp(0).build()); | ||
const restartChallenge = async () => { | ||
return new Promise <void >(resolve=>{ | ||
setTimeout(() => { | ||
setUser(Builder<User>().uid("1").challengeEndTimestamp(DateTime.now().plus({days: 8}).toMillis()).build()); | ||
resolve(); | ||
},3000); }); | ||
}; | ||
return ( | ||
<UserContext.Provider value={Builder<UserContextType>() | ||
.user(user) | ||
.restartChallenge(restartChallenge) | ||
.build()} | ||
> | ||
{children} | ||
</UserContext.Provider> | ||
); | ||
|
||
|
||
} | ||
export const RestartChallenge: Story = { | ||
|
||
render: () => { | ||
|
||
|
||
return ( | ||
<GlobalStylesProvider> | ||
<UserContextProvider> | ||
<RestartChallengeModal /> | ||
</UserContextProvider> | ||
</GlobalStylesProvider> | ||
); | ||
}, | ||
}; | ||
|