diff --git a/app/(main)/(home)/page.tsx b/app/(main)/(home)/page.tsx index b8e630a..05f2297 100644 --- a/app/(main)/(home)/page.tsx +++ b/app/(main)/(home)/page.tsx @@ -1,6 +1,7 @@ 'use client'; import * as React from 'react'; +import { useRouter } from 'next/navigation'; import { useAuth } from '@providers/AuthProvider'; import { Activity, Bike, Component, CircleSlash2, Target, Users, Annoyed, Frown, Laugh, Smile } from 'lucide-react'; import { @@ -22,6 +23,7 @@ import { HappinessSurvey, WorktypeSurvey, EmotionSurvey, Widget, AlertWidget, Sp const Home: React.FC = () => { const { user, isLoading, error } = useAuth(); + const router = useRouter(); const { data: emotions } = useSWRClient('/v1/emotions'); const { data: workKinds } = useSWRClient('/v1/workkinds/team'); const { data, mutate } = useSWRClient('/v1/dashboard/data'); @@ -52,6 +54,12 @@ const Home: React.FC = () => { return ; }; + React.useEffect(() => { + if (!isLoading && user && !user.hasTeam) { + router.push('/onboarding'); + } + }, [isLoading, user, router]); + if (isLoading) return ; if (error) return ; diff --git a/app/(main)/about/components/FAQAccordion.tsx b/app/(main)/about/components/FAQAccordion.tsx index 385474c..6cb69ce 100644 --- a/app/(main)/about/components/FAQAccordion.tsx +++ b/app/(main)/about/components/FAQAccordion.tsx @@ -31,12 +31,8 @@ const FAQAccordion: React.FC = () => ( - How can I delete my account? TODO + How can I delete my account? - To delete your account, please contact the server admins or host via our Discord channel. Once deleted, all your - data will be permanently removed from our servers. If you need assistance, please contact our support team.{' '} -
- or :
To delete your account, go to your account settings and follow the instructions for account deletion. Once deleted, all your data will be permanently removed from our servers. If you need assistance, please contact our support team. diff --git a/app/(main)/settings/account/page.tsx b/app/(main)/settings/account/page.tsx new file mode 100644 index 0000000..6040008 --- /dev/null +++ b/app/(main)/settings/account/page.tsx @@ -0,0 +1,65 @@ +'use client'; + +import * as React from 'react'; +import { useAuth } from '@providers/AuthProvider'; +import { useRouter } from 'next/navigation'; +import { + AlertDialog, + AlertDialogDescription, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogFooter, + AlertDialogCancel, + AlertDialogAction, +} from '@components/ui/AltertDialog/AlertDialog'; +import { Button } from '@components/ui/Buttons/Button'; +import Separator from '@components/ui/Separator/Separator'; +import useUserClient from '@hooks/useUserClient'; + +const AccountPage: React.FC = () => { + const { userId } = useAuth(); + const router = useRouter(); + const { deleteUser } = useUserClient(); + + const handleDelete = async () => { + try { + await deleteUser(userId); + router.replace('/login'); + } catch (error) { + console.warn('Error: ', error); + } + }; + + return ( + +
+
+

Delete account

+

Delete your yappi account permanently.

+
+ + + + +
+ + + +

Are you sure?

+
+ +

Deleting your account is irreversible. All your data will be lost.

+
+
+ + Cancel + handleDelete()}>Delete + +
+
+ ); +}; + +export default AccountPage; diff --git a/app/(main)/settings/components/ProfileForm.tsx b/app/(main)/settings/components/ProfileForm.tsx index 2860538..e20b81b 100644 --- a/app/(main)/settings/components/ProfileForm.tsx +++ b/app/(main)/settings/components/ProfileForm.tsx @@ -28,7 +28,7 @@ const FormSchema = z.object({ provider: z.string().nonempty('Provider is required'), name: z.string().nonempty('Name is required'), email: z.string().nonempty('Email is required').email('Please enter a valid email'), - githubUserName: z.string(), + githubUserName: z.string().optional(), }); type FormValue = z.infer; @@ -67,7 +67,11 @@ const ProfileForm: React.FC = () => { const onSubmit: SubmitHandler = async (data) => { try { - await update({ id: userId, username: data.username, githubUserName: data.githubUserName }); + await update({ + id: userId, + username: data.username, + githubUserName: data.githubUserName ? data.githubUserName : undefined, + }); toast.success('Profile has been updated'); } catch (error) { if (axios.isAxiosError(error)) { @@ -82,7 +86,7 @@ const ProfileForm: React.FC = () => { return (
- + { )} /> + ( + + GitHub Username + + + + + + )} + /> { )} /> - ( - - Github Username - - - - - - )} - /> diff --git a/app/(main)/settings/layout.tsx b/app/(main)/settings/layout.tsx index be7a92b..d2f2909 100644 --- a/app/(main)/settings/layout.tsx +++ b/app/(main)/settings/layout.tsx @@ -11,6 +11,10 @@ const settingsSidebarNavItems = [ title: 'Profile', href: '/settings', }, + { + title: 'Account', + href: '/settings/account', + }, { title: 'Appearance', href: '/settings/appearance', diff --git a/app/(main)/team/components/TeamMembersTable/columns.tsx b/app/(main)/team/components/TeamMembersTable/columns.tsx index 573be64..e0913be 100644 --- a/app/(main)/team/components/TeamMembersTable/columns.tsx +++ b/app/(main)/team/components/TeamMembersTable/columns.tsx @@ -4,6 +4,7 @@ import { TeamMemberWithUser } from '@/types/TeamMemberType'; import { ColumnDef } from '@tanstack/react-table'; import { Badge } from '@components/ui/Badge/Badge'; import cn from '@/lib/utils'; +import { format } from 'date-fns'; import DataTableColumnHeader from '@components/ui/Table/DataTableColumnHeader'; import { Asterisk } from 'lucide-react'; @@ -26,6 +27,15 @@ export const columns = (currentUserId: number): ColumnDef[] return username || '-'; }, }, + { + id: 'joinedAt', + accessorKey: 'joinedAt', + header: 'Joined At', + cell: ({ row }) => { + const { joinedAt } = row.original; + return joinedAt ? format(new Date(joinedAt), 'yyyy-MM-dd') : '-'; + }, + }, { accessorKey: 'role', header: 'Role', diff --git a/components/Header/Account.tsx b/components/Header/Account.tsx index e0360f2..412f32d 100644 --- a/components/Header/Account.tsx +++ b/components/Header/Account.tsx @@ -107,7 +107,7 @@ const Account: React.FC = () => {

Are you sure?

-

Log out of your yappi account.

+

Log out of your yappi account.

diff --git a/hooks/useUserClient.ts b/hooks/useUserClient.ts index 2163a4b..df6c532 100644 --- a/hooks/useUserClient.ts +++ b/hooks/useUserClient.ts @@ -13,11 +13,15 @@ const useUserClient = () => { const update = async (values: UpdatedUser): Promise> => client.put(`/v1/user/update`, values); + const deleteUser = async (userId?: string): Promise> => + client.delete(`/v1/user/delete/${userId}`); + const getUserById = async (userId: string): Promise> => client.get(`/v1/user/${userId}`); return { update, getUserById, + deleteUser, }; }; diff --git a/package-lock.json b/package-lock.json index bb3a550..e22e36a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -221,20 +221,20 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.6.tgz", - "integrity": "sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", "dependencies": { - "@floating-ui/utils": "^0.2.6" + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.9.tgz", - "integrity": "sha512-zB1PcI350t4tkm3rvUhSRKa9sT7vH5CrAbQxW+VaPYJXKAO0gsg4CTueL+6Ajp7XzAQC8CW4Jj1Wgqc0sB6oUQ==", + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", "dependencies": { "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.6" + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/react-dom": { @@ -250,9 +250,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.6.tgz", - "integrity": "sha512-0KI3zGxIUs1KDR/pjQPdJH4Z8nGBm0yJ5WRoRfdw1Kzeh45jkIfA0rmD0kBF6fKHH+xaH7g8y4jIXyAV5MGK3g==" + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "node_modules/@hookform/resolvers": { "version": "3.9.0", @@ -2459,9 +2459,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001650", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001650.tgz", - "integrity": "sha512-fgEc7hP/LB7iicdXHUI9VsBsMZmUmlVJeQP2qqQW+3lkqVhbmjEU8zp+h5stWeilX+G7uXuIUIIlWlDw9jdt8g==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "funding": [ { "type": "opencollective", @@ -4197,9 +4197,9 @@ } }, "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -4225,9 +4225,9 @@ } }, "node_modules/framer-motion": { - "version": "11.3.21", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.21.tgz", - "integrity": "sha512-D+hfIsvzV8eL/iycld4K+tKlg2Q2LdwnrcBEohtGw3cG1AIuNYATbT5RUqIM1ndsAk+EfGhoSGf0UaiFodc5Tw==", + "version": "11.3.24", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.24.tgz", + "integrity": "sha512-kl0YI7HwAtyV0VOAWuU/rXoOS8+z5qSkMN6rZS+a9oe6fIha6SC3vjJN6u/hBpvjrg5MQNdSnqnjYxm0WYTX9g==", "dependencies": { "tslib": "^2.4.0" }, @@ -7767,9 +7767,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", - "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.8.tgz", + "integrity": "sha512-GkP17r9GQkxgZ9FKHJQEnjJuKBcbFhMFzKu5slmN6NjlCuFnYJMQ8N4AZ6VrUyiRXlDtPKHkesuQ/MS913Nvdg==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", diff --git a/types/TeamMemberType.ts b/types/TeamMemberType.ts index 07badfb..043cede 100644 --- a/types/TeamMemberType.ts +++ b/types/TeamMemberType.ts @@ -10,6 +10,7 @@ export interface TeamMemberWithUser { id: number; user: User; teamId: number; + joinedAt: string; role: string; active: boolean; } diff --git a/types/UserType.ts b/types/UserType.ts index e9a14ee..0e7a8f9 100644 --- a/types/UserType.ts +++ b/types/UserType.ts @@ -10,7 +10,7 @@ export interface User { export interface UpdatedUser { id: string | undefined; username: string; - githubUserName: string; + githubUserName: string | undefined; } export interface UserWithProvider {