-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
made user login and new user forms (#41)
* made user login and new user forms * Update new user/login form with UX tweaks * Move account items to user menu in navbar * Whoop typo * Fix form popup animation * Organize form imports --------- Co-authored-by: Thomas Shaw <[email protected]>
- Loading branch information
1 parent
8cc712c
commit 4b6cb81
Showing
12 changed files
with
332 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
6 changes: 3 additions & 3 deletions
6
frontend/src/renderer/src/components/forms/new-asset-form.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
144 changes: 144 additions & 0 deletions
144
frontend/src/renderer/src/components/forms/new-user-form.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,144 @@ | ||
import { AnimatePresence, motion } from 'framer-motion'; | ||
import { SubmitHandler, useForm, useWatch } from 'react-hook-form'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
// import { useSelectedAsset } from '@renderer/hooks/use-asset-select'; | ||
// import useDownloads from '@renderer/hooks/use-downloads'; | ||
import Label from '../input/label'; | ||
import TextInput from '../input/text-input'; | ||
|
||
export interface NewUserFormData { | ||
firstName: string; // first name | ||
lastName: string; // last name | ||
pennkey: string; // username | ||
school: 'sas' | 'seas' | 'wharton'; | ||
password: string; // password | ||
} | ||
|
||
interface NewUserFormProps { | ||
afterSubmit?: SubmitHandler<NewUserFormData>; | ||
} | ||
|
||
// POST to /api/v1/assets/{uuid}/versions - Upload new version for a given asset | ||
export default function NewUserForm({ afterSubmit }: NewUserFormProps) { | ||
// const { commitChanges } = useDownloads(); | ||
// const { mutate: mutateSelectedAsset } = useSelectedAsset(); | ||
|
||
const { | ||
register, | ||
handleSubmit, | ||
formState: { isSubmitting }, | ||
control, | ||
} = useForm<NewUserFormData>({ | ||
defaultValues: { | ||
firstName: '', | ||
lastName: '', | ||
pennkey: '', | ||
school: 'seas', | ||
password: '', | ||
}, | ||
}); | ||
|
||
// -------------------------------------------- | ||
|
||
const submitHandler = async (data: NewUserFormData) => { | ||
// const { versions: downloadedVersions } = await window.api.ipc('assets:list-downloaded', null); | ||
// const downloaded = downloadedVersions.find(({ asset_id }) => asset_id === uuid); | ||
|
||
// if (!downloaded) { | ||
// console.error('No downloaded version found for asset', uuid); | ||
// return; | ||
// } | ||
|
||
// // Calling fetchClient.POST() | ||
// await commitChanges({ | ||
// asset_id: uuid, | ||
// semver: downloaded.semver, | ||
// message: data.message, | ||
// is_major: data.is_major, | ||
// }); | ||
|
||
// // refetch selected asset in case it's the one we updated | ||
// mutateSelectedAsset(); | ||
|
||
// Combine assetFiles from state with form data | ||
if (afterSubmit) afterSubmit(data); // Call the onSubmit function provided by props | ||
}; | ||
|
||
const [pennkey, school] = useWatch({ control, name: ['pennkey', 'school'] }); | ||
const computedEmail = pennkey ? `${pennkey}@${school}.upenn.edu` : undefined; | ||
|
||
return ( | ||
<form onSubmit={handleSubmit(submitHandler)}> | ||
<div className="flex flex-col gap-4"> | ||
<div className="grid gap-4 sm:grid-cols-2"> | ||
<TextInput | ||
label="First Name" | ||
placeholder="Ben" | ||
{...register('firstName', { required: true })} | ||
/> | ||
|
||
<TextInput | ||
label="Last Name" | ||
placeholder="Franklin" | ||
{...register('lastName', { required: true })} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<div className="grid gap-4 sm:grid-cols-2"> | ||
<TextInput | ||
label="Pennkey" | ||
placeholder="benfranklin" | ||
{...register('pennkey', { required: true })} | ||
/> | ||
|
||
<label {...register('school')}> | ||
<Label label="School" /> | ||
<select className="select select-bordered w-full" {...register('school')}> | ||
<option value="sas">CAS</option> | ||
<option value="seas">SEAS</option> | ||
<option value="wharton">Wharton</option> | ||
</select> | ||
</label> | ||
</div> | ||
<AnimatePresence initial={false}> | ||
{computedEmail && ( | ||
<motion.div | ||
className="overflow-hidden text-center" | ||
initial={{ height: 0 }} | ||
animate={{ height: 'auto' }} | ||
exit={{ height: 0 }} | ||
> | ||
<div className="mt-4 select-none text-base-content/50"> | ||
Email: <span className="text-base-content/100">{computedEmail}</span> | ||
</div> | ||
</motion.div> | ||
)} | ||
</AnimatePresence> | ||
</div> | ||
|
||
<TextInput | ||
label="Password" | ||
placeholder="••••••••" | ||
type="password" | ||
{...register('password', { required: true })} | ||
/> | ||
|
||
<div className="mt-6 flex w-full justify-center"> | ||
<button type="submit" className="btn btn-primary btn-wide" disabled={isSubmitting}> | ||
Create Account | ||
{isSubmitting && <span className="loading loading-spinner ml-2" />} | ||
</button> | ||
</div> | ||
|
||
<Link | ||
to="/user-login" | ||
className="mx-auto text-center text-primary/80 underline hover:text-primary/100" | ||
> | ||
Already have an account? Log in here. | ||
</Link> | ||
</div> | ||
</form> | ||
); | ||
} |
91 changes: 91 additions & 0 deletions
91
frontend/src/renderer/src/components/forms/user-login-form.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,91 @@ | ||
import { SubmitHandler, useForm } from 'react-hook-form'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
// import { useSelectedAsset } from '@renderer/hooks/use-asset-select'; | ||
// import useDownloads from '@renderer/hooks/use-downloads'; | ||
import TextInput from '../input/text-input'; | ||
|
||
export interface UserLoginFormData { | ||
username: string; // username | ||
password: string; // password | ||
} | ||
|
||
interface UserLoginFormProps { | ||
afterSubmit?: SubmitHandler<UserLoginFormData>; | ||
} | ||
|
||
// POST to /api/v1/assets/{uuid}/versions - Upload new version for a given asset | ||
export default function UserLoginForm({ afterSubmit }: UserLoginFormProps) { | ||
// const { commitChanges } = useDownloads(); | ||
// const { mutate: mutateSelectedAsset } = useSelectedAsset(); | ||
|
||
const { | ||
register, | ||
handleSubmit, | ||
formState: { isSubmitting }, | ||
} = useForm<UserLoginFormData>({ | ||
defaultValues: { | ||
username: '', | ||
password: '', | ||
}, | ||
}); | ||
|
||
// -------------------------------------------- | ||
|
||
const submitHandler = async (data: UserLoginFormData) => { | ||
// const { versions: downloadedVersions } = await window.api.ipc('assets:list-downloaded', null); | ||
// const downloaded = downloadedVersions.find(({ asset_id }) => asset_id === uuid); | ||
|
||
// if (!downloaded) { | ||
// console.error('No downloaded version found for asset', uuid); | ||
// return; | ||
// } | ||
|
||
// // Calling fetchClient.POST() | ||
// await commitChanges({ | ||
// asset_id: uuid, | ||
// semver: downloaded.semver, | ||
// message: data.message, | ||
// is_major: data.is_major, | ||
// }); | ||
|
||
// // refetch selected asset in case it's the one we updated | ||
// mutateSelectedAsset(); | ||
|
||
// Combine assetFiles from state with form data | ||
if (afterSubmit) afterSubmit(data); // Call the onSubmit function provided by props | ||
}; | ||
|
||
return ( | ||
<form onSubmit={handleSubmit(submitHandler)}> | ||
<div className="flex flex-col gap-4"> | ||
<TextInput | ||
label="Pennkey" | ||
placeholder="benfranklin" | ||
{...register('username', { required: true })} | ||
/> | ||
|
||
<TextInput | ||
label="Password" | ||
placeholder="••••••••" | ||
type="password" | ||
{...register('password', { required: true })} | ||
/> | ||
|
||
<div className="mt-6 flex w-full justify-center"> | ||
<button type="submit" className="btn btn-primary btn-wide" disabled={isSubmitting}> | ||
Login | ||
{isSubmitting && <span className="loading loading-spinner ml-2" />} | ||
</button> | ||
</div> | ||
|
||
<Link | ||
to="/new-user" | ||
className="mx-auto text-center text-primary/80 underline hover:text-primary/100" | ||
> | ||
Don't have a Griddle account? Create one here. | ||
</Link> | ||
</div> | ||
</form> | ||
); | ||
} |
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
21 changes: 21 additions & 0 deletions
21
frontend/src/renderer/src/components/layout/user-dropdown.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,21 @@ | ||
import { MdLogin, MdPerson } from 'react-icons/md'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
const UserDropdown = () => { | ||
return ( | ||
<div className="dropdown dropdown-end"> | ||
<div tabIndex={0} className="btn btn-circle m-1 flex items-center justify-center gap-2"> | ||
<MdPerson className="h-6 w-6" /> {/* Using the icon here */} | ||
</div> | ||
<ul tabIndex={0} className="menu dropdown-content w-52 rounded-box bg-base-100 p-2 shadow"> | ||
<li className=""> | ||
<Link to="/user-login"> | ||
<MdLogin /> Login to Griddle | ||
</Link> | ||
</li> | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UserDropdown; |
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,20 @@ | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import NewUserForm from '@renderer/components/forms/new-user-form'; | ||
import FormPopup from '@renderer/components/layout/form-popup'; | ||
// import { useAssetSelectStore } from '@renderer/hooks/use-asset-select'; | ||
|
||
export default function NewUserView() { | ||
const navigate = useNavigate(); | ||
// const setSelectedId = useAssetSelectStore((state) => state.setSelected); | ||
|
||
return ( | ||
<FormPopup title="Create your Griddle Account" onClose={() => navigate('/')}> | ||
<NewUserForm | ||
afterSubmit={() => { | ||
navigate('/'); | ||
}} | ||
/> | ||
</FormPopup> | ||
); | ||
} |
Oops, something went wrong.