Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add other tabs for settings page #118

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/(account)/join/steps/StepFour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function StepFour() {
/>
</div>
<div className="grid grid-cols-2 gap-4">
<Button onClick={prevStep} colour="orange" width="w-full" size="small">
<Button onClick={prevStep} colour="orange" width="w-full" size="small" fullWidth>
Back
</Button>
<Button
Expand All @@ -63,6 +63,7 @@ export default function StepFour() {
width="w-full"
size="small"
loading={createMember.isMutating}
fullWidth
>
Sign up
</Button>
Expand Down
10 changes: 9 additions & 1 deletion src/app/(account)/join/steps/StepOne.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function VerifyEmail() {
width="w-[19rem] md:w-[25.5rem]"
type="submit"
loading={verifyEmailLoading}
fullWidth
>
Verify Email
</Button>
Expand Down Expand Up @@ -153,7 +154,13 @@ export default function StepOne() {

return (
<div>
<Button onClick={handleGoogleSignUp} colour="white" width="w-full" size="small">
<Button
onClick={handleGoogleSignUp}
colour="white"
width="w-full"
size="small"
fullWidth
>
<FcGoogle className="mb-0.5 mr-2 inline-block text-xl" />
Continue with Google
</Button>
Expand Down Expand Up @@ -181,6 +188,7 @@ export default function StepOne() {
type="submit"
size="small"
loading={emailJoinLoading}
fullWidth
>
Continue
</Button>
Expand Down
21 changes: 4 additions & 17 deletions src/app/(account)/join/steps/StepThree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,10 @@ import type { STUDENT_STATUSES } from '@/constants/student-info';
import { AGE_BRACKETS, DEGREES, GENDERS, STUDENT_TYPES } from '@/constants/student-info';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import type { z } from 'zod';
import { stepThreeSchema } from '../../schemas';
import { useJoinUsStep, useJoinUsStudentInfo, useSetJoinUsHeading } from '../store';

export const stepThreeSchema = z.object({
ageBracket: z.enum(AGE_BRACKETS, {
errorMap: () => ({ message: 'Please select an age bracket' }),
}),
gender: z.enum(GENDERS, { errorMap: () => ({ message: 'Please select a gender' }) }),
degree: z
.enum(DEGREES, { errorMap: () => ({ message: 'Please select a degree' }) })
.or(z.literal('')),
studentType: z
.enum(STUDENT_TYPES, {
errorMap: () => ({ message: 'Please select a student type' }),
})
.or(z.literal('')),
});
export type StepThreeData = z.infer<typeof stepThreeSchema>;

/** Get schema with student check */
Expand Down Expand Up @@ -103,10 +90,10 @@ export default function StepThree() {
</>
)}
<div className="grid grid-cols-2 gap-4">
<Button onClick={prevStep} colour="orange" width="w-full" size="small">
<Button onClick={prevStep} colour="orange" width="w-full" size="small" fullWidth>
Back
</Button>
<Button type="submit" colour="orange" width="w-full" size="small">
<Button type="submit" colour="orange" width="w-full" size="small" fullWidth>
Continue
</Button>
</div>
Expand Down
19 changes: 3 additions & 16 deletions src/app/(account)/join/steps/StepTwo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,10 @@ import { useUser } from '@clerk/clerk-react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { firstNameSchema, lastNameSchema } from '../../schemas';
import type { z } from 'zod';
import { stepTwoSchema } from '../../schemas';
import { useJoinUsStep, useJoinUsStudentInfo, useSetJoinUsHeading } from '../store';

export const stepTwoSchema = z.object({
firstName: firstNameSchema,
lastName: lastNameSchema,
studentStatus: z.enum(STUDENT_STATUSES, {
errorMap: () => ({ message: 'Please select a valid status' }),
}),
studentId: z
.string()
.regex(/^a\d{7}$/, {
message: 'Please enter a valid student ID (format: aXXXXXXX)',
})
.or(z.literal('')),
});
export type StepTwoData = z.infer<typeof stepTwoSchema>;

const validationSchema = stepTwoSchema.refine(
Expand Down Expand Up @@ -70,7 +57,7 @@ export default function StepTwo() {
{form.watch('studentStatus') === 'At The University of Adelaide' && (
<ControlledField label="Student ID" control={form.control} name="studentId" />
)}
<Button colour="orange" width="w-full" size="small" type="submit">
<Button colour="orange" width="w-full" size="small" type="submit" fullWidth>
Continue
</Button>
</form>
Expand Down
38 changes: 38 additions & 0 deletions src/app/(account)/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import {
AGE_BRACKETS,
DEGREES,
GENDERS,
STUDENT_STATUSES,
STUDENT_TYPES,
} from '@/constants/student-info';
import { z } from 'zod';

export const emailSchema = z
Expand Down Expand Up @@ -35,3 +42,34 @@ export const codeSchema = z
.regex(/^\d+$/, {
message: 'Code must be numeric',
});

export const stepTwoSchema = z.object({
firstName: firstNameSchema,
lastName: lastNameSchema,
studentStatus: z.enum(STUDENT_STATUSES, {
errorMap: () => ({ message: 'Please select a valid status' }),
}),
studentId: z
.string()
.regex(/^a\d{7}$/, {
message: 'Please enter a valid student ID (format: aXXXXXXX)',
})
.or(z.literal('')),
});

export const stepThreeSchema = z.object({
ageBracket: z.enum(AGE_BRACKETS, {
errorMap: () => ({ message: 'Please select an age bracket' }),
}),
gender: z.enum(GENDERS, { errorMap: () => ({ message: 'Please select a gender' }) }),
degree: z
.enum(DEGREES, { errorMap: () => ({ message: 'Please select a degree' }) })
.or(z.literal('')),
studentType: z
.enum(STUDENT_TYPES, {
errorMap: () => ({ message: 'Please select a student type' }),
})
.or(z.literal('')),
});

export const infoSchema = stepTwoSchema.merge(stepThreeSchema);
11 changes: 7 additions & 4 deletions src/app/(account)/settings/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
'use client';

import type { MembershipPayment } from '@/server/verify-membership-payment';
import { useRouter } from 'next/navigation';
import React, { useState } from 'react';
import Sidebar from './Sidebar';
import type { SettingData } from './page';
import AccountSettings from './tabs/AccountSettings';
import MembershipSettings from './tabs/MembershipSettings';
import PersonalInfoSettings from './tabs/PersonalInfoSettings';

export const TAB_NAMES = ['Account', 'Personal Info', 'Membership', 'Notifications'] as const;
jsun969 marked this conversation as resolved.
Show resolved Hide resolved
export type TabNames = (typeof TAB_NAMES)[number];

export type SettingData = { membershipPayment: MembershipPayment };
export type SettingTabProps = { settingData: SettingData };
type SettingTabComponent = ({ settingData }: SettingTabProps) => React.ReactNode;
const SETTING_TABS = {
Account: () => <div>Coming soon</div>,
'Personal Info': () => <div>Coming soon</div>,
Account: AccountSettings,
'Personal Info': PersonalInfoSettings,
Membership: MembershipSettings,
// TODO(#31): Email notifications (enable tab like below)
// Notifications: NotificationsSettings,
Notifications: () => <div>Coming soon</div>,
} as const satisfies Record<TabNames, SettingTabComponent>;

Expand Down
27 changes: 25 additions & 2 deletions src/app/(account)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import FancyRectangle from '@/components/FancyRectangle';
import Title from '@/components/Title';
import { db } from '@/db';
import { checkUserExists } from '@/server/check-user-exists';
import { verifyMembershipPayment } from '@/server/verify-membership-payment';
import { currentUser } from '@clerk/nextjs';
Expand All @@ -13,12 +14,34 @@ export const metadata: Metadata = {
robots: { index: false, follow: false },
};

const getSettingData = async (userId: string) => {
const membershipPayment = await verifyMembershipPayment(userId);

const { email, ...personalInfo } = (await db.query.memberTable.findFirst({
where: (members, { eq }) => eq(members.clerkId, userId),
columns: {
firstName: true,
lastName: true,
ageBracket: true,
gender: true,
studentType: true,
studentStatus: true,
studentId: true,
degree: true,
email: true,
},
}))!;

return { membershipPayment, personalInfo, email };
};
export type SettingData = Awaited<ReturnType<typeof getSettingData>>;

export default async function SettingsPage() {
const user = await currentUser();
if (!user) return notFound();

const exists = await checkUserExists(user.id);
const membershipPayment = await verifyMembershipPayment(user.id);
const settingData = await getSettingData(user.id);

return (
<main className="flex flex-col items-center gap-8 md:gap-16">
Expand All @@ -28,7 +51,7 @@ export default async function SettingsPage() {
<section className="w-full max-w-[62rem]">
<FancyRectangle colour="purple" offset="8" filled fullWidth>
{exists ? (
<Settings settingData={{ membershipPayment }} />
<Settings settingData={settingData} />
) : (
<h2 className="text-2xl">
Please finishing{' '}
Expand Down
Loading
Loading