-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/DEAR-117' into DEAR-122-Frontend
- Loading branch information
Showing
19 changed files
with
729 additions
and
128 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as React from 'react'; | ||
import type { Metadata } from 'next'; | ||
import 'styles/globals.css'; | ||
import outfit from 'styles/fonts'; | ||
import ThemeProvider from '@providers/ThemeProvider'; | ||
import NextAuthProvider from '@providers/NextAuthProvider'; | ||
import { AuthProvider } from '@providers/AuthProvider'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'yappi', | ||
description: 'Your personal productivity assistant', | ||
}; | ||
|
||
export default function RootLayout({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<html lang="en" suppressHydrationWarning> | ||
<body className={`${outfit.variable} font-outfit`}> | ||
<NextAuthProvider> | ||
<AuthProvider> | ||
<ThemeProvider attribute="class" defaultTheme="light" enableSystem> | ||
<main> | ||
<div>{children}</div> | ||
</main> | ||
</ThemeProvider> | ||
</AuthProvider> | ||
</NextAuthProvider> | ||
</body> | ||
</html> | ||
); | ||
} |
130 changes: 130 additions & 0 deletions
130
app/(onboarding)/onboarding/components/CreateTeamDialog.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,130 @@ | ||
'use client'; | ||
|
||
import * as React from 'react'; | ||
import { DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@components/ui/Dialog/Dialog'; | ||
import { Button } from '@components/ui/Buttons/Button'; | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { z } from 'zod'; | ||
import { useForm, SubmitHandler } from 'react-hook-form'; | ||
import Input from '@components/ui/Input/Input'; | ||
import { useAuth } from '@providers/AuthProvider'; | ||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@components/ui/Form/Form'; | ||
import useTeamClient from '@hooks/useTeamClient'; | ||
import { BadgeCheck, Loader2, Clipboard, Check } from 'lucide-react'; | ||
import { Team } from '@/types/TeamType'; | ||
|
||
const FormSchema = z.object({ | ||
name: z.string().nonempty('Team name is required'), | ||
}); | ||
|
||
type FormValues = z.infer<typeof FormSchema>; | ||
|
||
const CreateTeamDialog: React.FC = () => { | ||
const { userId } = useAuth(); | ||
const { createTeam } = useTeamClient(); | ||
const [isLoading, setIsLoading] = React.useState<boolean>(false); | ||
const [copied, setCopied] = React.useState<boolean>(false); | ||
const [createdTeam, setCreatedTeam] = React.useState<Team | null>(null); | ||
const inputRef = React.useRef<HTMLInputElement>(null); | ||
|
||
const form = useForm<FormValues>({ | ||
resolver: zodResolver(FormSchema), | ||
defaultValues: { | ||
name: '', | ||
}, | ||
mode: 'onSubmit', | ||
}); | ||
|
||
const handleSubmit: SubmitHandler<FormValues> = async (data) => { | ||
try { | ||
setIsLoading(true); | ||
await createTeam({ name: data.name, userId }).then((response) => { | ||
setCreatedTeam(response.data); | ||
}); | ||
} catch (error) { | ||
console.error(error); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}; | ||
|
||
const copyToClipboard = () => { | ||
const inputValue = inputRef.current?.value; | ||
if (inputValue) { | ||
navigator.clipboard.writeText(inputValue).then(() => { | ||
setCopied(true); | ||
setTimeout(() => setCopied(false), 2000); | ||
}); | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<DialogHeader> | ||
<DialogTitle> | ||
{createdTeam ? ( | ||
<div className="flex items-center"> | ||
<BadgeCheck className="mr-2 h-5 w-5" /> | ||
Woho! | ||
</div> | ||
) : ( | ||
'Create a team' | ||
)} | ||
</DialogTitle> | ||
<DialogDescription> | ||
{createdTeam ? ( | ||
<span className="max-w-md"> | ||
Your yappi team was created successfully. Start your happiness journey and invite new team members with | ||
the code below: | ||
</span> | ||
) : ( | ||
'Give your team a name and get started.' | ||
)} | ||
</DialogDescription> | ||
</DialogHeader> | ||
{!createdTeam ? ( | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-8"> | ||
<FormField | ||
control={form.control} | ||
name="name" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Team name</FormLabel> | ||
<FormControl> | ||
<Input className="resize-none text-sm font-light" placeholder="Name" {...field} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<DialogFooter> | ||
{!isLoading ? ( | ||
<Button type="submit">Create Team</Button> | ||
) : ( | ||
<Button disabled> | ||
<Loader2 className="mr-2 h-4 w-4 animate-spin" /> | ||
Please wait | ||
</Button> | ||
)} | ||
</DialogFooter> | ||
</form> | ||
</Form> | ||
) : ( | ||
<> | ||
<div className="flex w-full items-center space-x-2"> | ||
<Button variant="outline" onClick={() => copyToClipboard()}> | ||
{copied ? <Check className="h-4 w-4" /> : <Clipboard className="h-4 w-4" />} | ||
</Button> | ||
<Input ref={inputRef} disabled value={createdTeam?.code} /> | ||
</div> | ||
<DialogFooter> | ||
<Button className="mt-8 px-8">Continue</Button> | ||
</DialogFooter> | ||
</> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default CreateTeamDialog; |
114 changes: 114 additions & 0 deletions
114
app/(onboarding)/onboarding/components/JoinTeamDialog.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,114 @@ | ||
'use client'; | ||
|
||
import * as React from 'react'; | ||
import { DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@components/ui/Dialog/Dialog'; | ||
import { Button } from '@components/ui/Buttons/Button'; | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { z } from 'zod'; | ||
import { useForm, SubmitHandler } from 'react-hook-form'; | ||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@components/ui/Form/Form'; | ||
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@components/ui/InputOTP/InputOTP'; | ||
import { REGEXP_ONLY_DIGITS_AND_CHARS } from 'input-otp'; | ||
import { useAuth } from '@providers/AuthProvider'; | ||
import useTeamClient from '@hooks/useTeamClient'; | ||
import { BadgeCheck, Loader2 } from 'lucide-react'; | ||
import { Team } from '@/types/TeamType'; | ||
|
||
const FormSchema = z.object({ | ||
code: z.string().min(4, { | ||
message: 'Code must be 4 digits', | ||
}), | ||
}); | ||
|
||
type FormValues = z.infer<typeof FormSchema>; | ||
|
||
const JoinTeamDialog: React.FC = () => { | ||
const { userId } = useAuth(); | ||
const { joinTeam } = useTeamClient(); | ||
const [isLoading, setIsLoading] = React.useState<boolean>(false); | ||
const [joinedTeam, setJoinedTeam] = React.useState<Team | null>(null); | ||
|
||
const form = useForm<FormValues>({ | ||
resolver: zodResolver(FormSchema), | ||
defaultValues: { | ||
code: '', | ||
}, | ||
mode: 'onSubmit', | ||
}); | ||
|
||
const handleSubmit: SubmitHandler<FormValues> = async (data) => { | ||
try { | ||
setIsLoading(true); | ||
await joinTeam({ code: data.code, userId }).then((response) => { | ||
setJoinedTeam(response.data); | ||
}); | ||
} catch (error) { | ||
console.error(error); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<DialogHeader> | ||
<DialogTitle> | ||
{joinedTeam ? ( | ||
<div className="flex items-center"> | ||
<BadgeCheck className="mr-2 h-5 w-5" /> | ||
Woho! | ||
</div> | ||
) : ( | ||
'Join a team' | ||
)} | ||
</DialogTitle> | ||
<DialogDescription> | ||
{joinedTeam ? ( | ||
<span className="max-w-md"> | ||
You have successfully joined the team{' '} | ||
<span className="font-bold text-black underline">{joinedTeam.name}</span>. | ||
</span> | ||
) : ( | ||
'Fill the four-digit code, this code should be provided to you by a admin.' | ||
)} | ||
</DialogDescription> | ||
</DialogHeader> | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-8"> | ||
<FormField | ||
control={form.control} | ||
name="code" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Team code</FormLabel> | ||
<FormControl> | ||
<InputOTP maxLength={4} pattern={REGEXP_ONLY_DIGITS_AND_CHARS} {...field}> | ||
<InputOTPGroup> | ||
<InputOTPSlot index={0} /> | ||
<InputOTPSlot index={1} /> | ||
<InputOTPSlot index={2} /> | ||
<InputOTPSlot index={3} /> | ||
</InputOTPGroup> | ||
</InputOTP> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<DialogFooter> | ||
{!isLoading ? ( | ||
<Button type="submit">Join Team</Button> | ||
) : ( | ||
<Button disabled> | ||
<Loader2 className="animate-sping mr-2 h-4 w-4" /> | ||
Please wait | ||
</Button> | ||
)} | ||
</DialogFooter> | ||
</form> | ||
</Form> | ||
</> | ||
); | ||
}; | ||
|
||
export default JoinTeamDialog; |
Oops, something went wrong.