Skip to content

Commit

Permalink
Safities User Settings (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobellerbrock authored Sep 11, 2024
1 parent 129c195 commit 9b001c4
Show file tree
Hide file tree
Showing 12 changed files with 1,510 additions and 114 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ yarn-error.log*

# vscode
.vscode

#Jetbrians
.idea
168 changes: 160 additions & 8 deletions apps/web/src/actions/user-profile-mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,192 @@ import { revalidatePath } from "next/cache";
// TODO: Add skill updating
export const modifyRegistrationData = authenticatedAction(
z.object({
bio: z.string().max(500),
skills: z.string().max(100),
age: z.number(),
gender: z.string(),
race: z.string(),
ethnicity: z.string(),
wantsToReceiveMLHEmails: z.boolean(),
university: z.string(),
major: z.string(),
levelOfStudy: z.string(),
shortID: z.string(),
hackathonsAttended: z.number(),
softwareExperience: z.string(),
heardFrom: z.string().nullish(),
shirtSize: z.string(),
dietRestrictions: z.string().array(),
accommodationNote: z.string().nullish(),
GitHub: z.string().nullish(),
LinkedIn: z.string().nullish(),
PersonalWebsite: z.string().nullish(),
}),
async ({ bio, skills }, { userId }) => {
async (
{
age,
gender,
race,
ethnicity,
wantsToReceiveMLHEmails,
university,
major,
levelOfStudy,
shortID,
hackathonsAttended,
softwareExperience,
heardFrom,
shirtSize,
dietRestrictions,
accommodationNote,
GitHub,
LinkedIn,
PersonalWebsite,
},
{ userId },
) => {
const user = await db.query.users.findFirst({
where: eq(users.clerkID, userId),
});
if (!user) throw new Error("User not found");
await db
.update(registrationData)
.set({
age,
gender,
race,
ethnicity,
wantsToReceiveMLHEmails,
university,
major,
levelOfStudy,
shortID,
hackathonsAttended,
softwareExperience,
heardFrom,
shirtSize,
dietRestrictions,
accommodationNote,
GitHub,
LinkedIn,
PersonalWebsite,
})
.where(eq(registrationData.clerkID, user.clerkID));
return {
success: true,
newAge: age,
newGender: gender,
newRace: race,
newEthnicity: ethnicity,
newWantsToReceiveMLHEmails: wantsToReceiveMLHEmails,
newUniversity: university,
newMajor: major,
newLevelOfStudy: levelOfStudy,
newShortID: shortID,
newHackathonsAttended: hackathonsAttended,
newSoftwareExperience: softwareExperience,
newHeardFrom: heardFrom,
newShirtSize: shirtSize,
newDietaryRestrictions: dietRestrictions,
newAccommodationNote: accommodationNote,
newGitHub: GitHub,
newLinkedIn: LinkedIn,
newPersonalWebsite: PersonalWebsite,
};
},
);

export const modifyResume = authenticatedAction(
z.object({
resume: z.string(),
}),
async ({ resume }, { userId }) => {
const user = await db.query.users.findFirst({
where: eq(users.clerkID, userId),
});
if (!user) throw new Error("User not found");
await db
.update(registrationData)
.set({ resume })
.where(eq(registrationData.clerkID, user.clerkID));
return {
success: true,
newResume: resume,
};
},
);

export const modifyProfileData = authenticatedAction(
z.object({
pronouns: z.string(),
bio: z.string(),
skills: z.string().array(),
discordUsername: z.string(),
}),
async ({ pronouns, bio, skills, discordUsername }, { userId }) => {
const user = await db
.select()
.from(users)
.leftJoin(profileData, eq(users.hackerTag, profileData.hackerTag))
.where(eq(users.clerkID, userId));
if (!user || !user[0].profile_data) {
throw new Error("User not found");
}
await db
.update(profileData)
.set({ bio })
.where(eq(profileData.hackerTag, user.hackerTag));
return { success: true, newbio: bio };
.set({ pronouns, bio, skills, discordUsername })
.where(eq(profileData.hackerTag, user[0].profile_data.hackerTag));
return {
success: true,
newPronouns: pronouns,
newBio: bio,
newSkills: skills,
newDiscord: discordUsername,
};
},
);

export const modifyAccountSettings = authenticatedAction(
z.object({
firstName: z.string().min(1).max(50),
lastName: z.string().min(1).max(50),
//email: z.string().min(1).max(50),
hackerTag: z.string().min(1).max(50),
hasSearchableProfile: z.boolean(),
}),
async ({ firstName, lastName }, { userId }) => {
async (
{ firstName, lastName, hackerTag, hasSearchableProfile },
{ userId },
) => {
const user = await db.query.users.findFirst({
where: eq(users.clerkID, userId),
});
if (!user) throw new Error("User not found");
let oldHackerTag = user.hackerTag; // change when hackertag is not PK on profileData table
if (oldHackerTag != hackerTag) {
const lookupByHackerTag = await db.query.users.findFirst({
where: eq(users.hackerTag, hackerTag.toLowerCase()),
}); // copied from /api/registration/create
if (lookupByHackerTag) {
return {
success: false,
message: "hackertag_not_unique",
};
}
}
await db
.update(users)
.set({ firstName, lastName })
.set({ firstName, lastName, hackerTag, hasSearchableProfile })
.where(eq(users.clerkID, userId));
await db
.update(profileData) // see above comment
.set({ hackerTag })
.where(eq(profileData.hackerTag, oldHackerTag));
return {
success: true,
newFirstName: firstName,
newLastName: lastName,
//newEmail: email,
newHackerTag: hackerTag,
newHasSearchableProfile: hasSearchableProfile,
};
},
);
Expand Down
14 changes: 9 additions & 5 deletions apps/web/src/app/settings/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ export default async function ({ children }: { children: ReactNode }) {
</div>
</div>
</div>
<div>
<aside className="sticky top-20 hidden h-screen md:block">
{/* <SettingsSection name="Settings" path="/settings" /> */}
<SettingsSection name="Account" path="/settings/account" />
<SettingsSection name="Profile" path="/settings/profile" />
</div>
<div className="col-span-4">{children}</div>
<SettingsSection name="Account" path="/settings#account" />
<SettingsSection name="Profile" path="/settings#profile" />
<SettingsSection
name="Registration"
path="/settings#registration"
/>
</aside>
<div className="col-span-4 mb-20 ml-5">{children}</div>
</div>
</>
);
Expand Down
44 changes: 42 additions & 2 deletions apps/web/src/app/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
export default function Page() {
return <span>howdy</span>;
import AccountSettings from "@/components/settings/AccountSettings";
import { users } from "db/schema";
import { eq } from "db/drizzle";
import { auth } from "@clerk/nextjs";
import { db } from "db";
import { redirect } from "next/navigation";
import ProfileSettings from "@/components/settings/ProfileSettings";
import RegistrationSettings from "@/components/settings/RegistrationSettings";

export default async function Page() {
const { userId } = auth();
if (!userId) return redirect("/sign-in");
const user = await db.query.users.findFirst({
with: {
registrationData: true,
profileData: true,
},
where: eq(users.clerkID, userId!),
});
if (!user) return redirect("/sign-in");

function Header({ tag }: { tag: string }) {
return (
<h1
id={tag.toLowerCase()}
className="mt-10 pb-5 text-4xl font-bold"
>
{tag}
</h1>
);
}

return (
<div>
<Header tag="Account" />
<AccountSettings user={user} />
<Header tag="Profile" />
<ProfileSettings profile={user.profileData} />
<Header tag={"Registration"} />
<RegistrationSettings />
</div>
);
}
26 changes: 0 additions & 26 deletions apps/web/src/app/settings/profile/page.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import AccountSettings from "@/components/settings/AccountSettings";
import { users } from "db/schema";
import { eq } from "db/drizzle";
import RegisterFormSettings from "@/components/settings/RegistrationForm/RegisterFormSettings";
import { auth } from "@clerk/nextjs";
import { db } from "db";
import { eq } from "db/drizzle";
import { users } from "db/schema";
import { redirect } from "next/navigation";

export default async function Page() {
const { userId } = auth();
if (!userId) return redirect("/sign-in");
const user = await db.query.users.findFirst({
with: { registrationData: true },
with: {
registrationData: true,
profileData: true,
},
where: eq(users.clerkID, userId!),
});
if (!user) return redirect("/sign-in");
return <AccountSettings user={user} />;
}

export const runtime = "edge";
return <RegisterFormSettings data={user.registrationData} />;
}
1 change: 1 addition & 0 deletions apps/web/src/components/registration/RegisterForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ export default function RegisterForm({ defaultEmail }: RegisterFormProps) {
</FormItem>
)}
/>

<FormField
control={form.control}
name="levelOfStudy"
Expand Down
Loading

0 comments on commit 9b001c4

Please sign in to comment.