-
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.
Refining UI and adding image fixes #168 auth and admin login (#169) adding way to delete image and split codes into separate components changing icons and adjust way to update user removing unused file refactoring my codes to solve some issues splitting some components into smaller ones removing some lines not being used adjusting button to remove image adjusting some functionality and UI refactoring code to reduce some issue split some components into smaller one fixing issues related to routes making some changes to UI rebasing changes from develop stoping yarn to be tracked
- Loading branch information
1 parent
9fcad26
commit f8c3d66
Showing
18 changed files
with
677 additions
and
20,828 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,26 @@ | ||
import React from "react"; | ||
import { UseFormReturn } from "react-hook-form"; | ||
import { ThreeDots } from "react-loader-spinner"; | ||
import { TuserSchema } from "../../utils/userSchema"; | ||
import useImageUpload from "../../components/updateUserProfile/useImagePreview"; | ||
import ImagePreview from "../../components/updateUserProfile/imagePreview"; | ||
|
||
interface ImageUploadProps { | ||
form: UseFormReturn<TuserSchema>; | ||
} | ||
|
||
const ImageUpload: React.FC<ImageUploadProps> = ({ form }) => { | ||
const { previewImage, isUploading } = useImageUpload(form); | ||
|
||
return ( | ||
|
||
<div className="w-full absolute top-20 px-8"> | ||
<span> | ||
{isUploading && <ThreeDots height="30" width="30" color="#ffffff" />} | ||
</span> | ||
<ImagePreview previewImage={previewImage} form={form} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ImageUpload; |
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,57 @@ | ||
import React, { useState } from "react"; | ||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons"; | ||
|
||
interface PasswordInputProps { | ||
register: any; | ||
errors: any; | ||
} | ||
|
||
const PasswordInput: React.FC<PasswordInputProps> = ({ register, errors }) => { | ||
const [showPassword, setShowPassword] = useState(false); | ||
|
||
const handleClickShowPassword = () => { | ||
setShowPassword((prev) => !prev); | ||
}; | ||
|
||
return ( | ||
<> | ||
<div className="relative flex-1 rounded"> | ||
<div className="flex flex-1 flex-col gap-2"> | ||
<label htmlFor="" className="text-white"> | ||
Password | ||
</label> | ||
<input | ||
type={showPassword ? "text" : "password"} | ||
{...register("password")} | ||
placeholder="Change password" | ||
className="w-full pl-4 py-2 rounded-md border-[1px] bg-transparent dark:text-white" | ||
/> | ||
</div> | ||
|
||
<div | ||
onClick={handleClickShowPassword} | ||
className="absolute right-4 top-10" | ||
aria-label="Toggle password visibility" | ||
> | ||
{showPassword ? ( | ||
<FontAwesomeIcon | ||
icon={faEye} | ||
className="text-gray-400 dark:text-white" | ||
/> | ||
) : ( | ||
<FontAwesomeIcon | ||
icon={faEyeSlash} | ||
className="text-gray-400 dark:text-white" | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
{errors.password && ( | ||
<p className="text-sm text-red-600">{errors.password.message}</p> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default PasswordInput; |
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 @@ | ||
import React from "react"; | ||
import { UseFormReturn } from "react-hook-form"; | ||
import { Link } from "react-router-dom"; | ||
import { ThreeDots } from "react-loader-spinner"; | ||
import { TuserSchema } from "../../utils/userSchema"; | ||
import PasswordInput from "./PasswordInput"; | ||
import useImageUpload from "./useImagePreview"; | ||
|
||
interface ProfileFormProps { | ||
form: UseFormReturn<TuserSchema>; | ||
onSubmit: (data: TuserSchema) => Promise<void>; | ||
} | ||
|
||
const ProfileForm: React.FC<ProfileFormProps> = ({ | ||
form, | ||
onSubmit, | ||
}) => { | ||
const { | ||
register, | ||
handleSubmit, | ||
formState: { errors, isSubmitting }, | ||
} = form; | ||
const { previewImage, isUploading, handleImageChange } = useImageUpload(form); | ||
|
||
|
||
return ( | ||
<form | ||
className="w-[60%] flex flex-col gap-6 rounded-md px-10 py-12 " | ||
onSubmit={handleSubmit(onSubmit)} | ||
> | ||
<label className="text-xl font-semibold text-white pb-1">Edit Profile</label> | ||
<hr className="w-32 mt-[-25px] border-2 border-green " /> | ||
<div className="w-full justify-between flex gap-16 flex-wrap"> | ||
<div className="flex flex-col flex-1 gap-2"> | ||
<label htmlFor="" className=" dark:text-white"> | ||
First Name | ||
</label> | ||
<input | ||
type="text" | ||
{...register("firstname")} | ||
className="flex-1 pl-4 py-2 rounded border-[1px] border-black bg-transparent dark:text-white dark:border-white" | ||
/> | ||
{errors.firstname && ( | ||
<p className="text-sm text-red-600">{errors.firstname.message}</p> | ||
)} | ||
</div> | ||
<div className="flex flex-col flex-1 gap-2"> | ||
<label htmlFor="" className="text-white"> | ||
Last Name | ||
</label> | ||
<input | ||
type="text" | ||
{...register("lastname")} | ||
className="flex-1 pl-4 py-2 rounded-md border-[1px] bg-transparent dark:text-white" | ||
/> | ||
{errors.lastname && ( | ||
<p className="text-sm text-red-600">{errors.lastname.message}</p> | ||
)} | ||
</div> | ||
</div> | ||
|
||
<div className="w-full justify-between flex gap-16 flex-wrap"> | ||
<div className="flex-1 flex flex-col gap-2"> | ||
<label htmlFor="" className="text-white"> | ||
Code | ||
</label> | ||
<input | ||
type="text" | ||
{...register("code")} | ||
className="flex-1 pl-4 py-2 rounded-md border-[1px] bg-transparent dark:text-white" | ||
/> | ||
{errors.code && ( | ||
<p className="text-sm text-red-600">{errors.code.message}</p> | ||
)} | ||
</div> | ||
<div className="flex flex-1 flex-col gap-2"> | ||
<label htmlFor="" className="text-white"> | ||
Telephone | ||
</label> | ||
<input | ||
type="text" | ||
{...register("telephone")} | ||
className="flex-1 pl-4 py-2 rounded-md border-[1px] bg-transparent dark:text-white" | ||
/> | ||
{errors.telephone && ( | ||
<p className="text-sm text-red-600">{errors.telephone.message}</p> | ||
)} | ||
</div> | ||
</div> | ||
<div className="w-full flex gap-16 justify-between flex-wrap "> | ||
<div className="flex flex-1 flex-col gap-2"> | ||
<label htmlFor="" className="text-white"> | ||
</label> | ||
<input | ||
type="text" | ||
{...register("email")} | ||
className="flex-1 pl-4 py-2 rounded-md border-[1px] bg-transparent dark:text-white" | ||
/> | ||
{errors.email && ( | ||
<p className="text-sm text-red-600">{errors.email.message}</p> | ||
)} | ||
</div> | ||
<PasswordInput register={register} errors={errors} /> | ||
</div> | ||
|
||
<div className=""> | ||
<input | ||
type="file" | ||
onChange={handleImageChange} | ||
className="pl-4 py-2 rounded dark:bg-transparent dark:text-white" | ||
/> | ||
</div> | ||
<div className="flex gap-4"> | ||
<button | ||
className="py-2 mt-2 w-64 text-white font-medium bg-green rounded flex justify-center hover:bg-emerald-600" | ||
disabled={isSubmitting} | ||
> | ||
{isSubmitting ? ( | ||
<ThreeDots height="20" width="30" color="#ffffff" /> | ||
) : ( | ||
"UPDATE" | ||
)} | ||
</button> | ||
</div> | ||
</form> | ||
); | ||
}; | ||
|
||
export default ProfileForm; |
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,50 @@ | ||
import React from "react"; | ||
import { UseFormReturn } from "react-hook-form"; | ||
import { CiImageOff } from "react-icons/ci"; | ||
import { toast } from "react-toastify"; | ||
import { TuserSchema } from "../../utils/userSchema"; | ||
|
||
interface ImagePreviewProps { | ||
previewImage: string | null; | ||
form: UseFormReturn<TuserSchema>; | ||
} | ||
|
||
const DEFAULT_IMAGE = | ||
"https://t4.ftcdn.net/jpg/01/24/65/69/360_F_124656969_x3y8YVzvrqFZyv3YLWNo6PJaC88SYxqM.jpg"; | ||
|
||
const ImagePreview: React.FC<ImagePreviewProps> = ({ previewImage, form }) => { | ||
const { setValue, watch } = form; | ||
const currentPicture = watch("picture"); | ||
|
||
const deletePreviewImage = () => { | ||
if (currentPicture === DEFAULT_IMAGE) { | ||
toast.info("This is the default image"); | ||
} else { | ||
setValue("picture", DEFAULT_IMAGE); | ||
toast.error("Image is removed"); | ||
} | ||
}; | ||
|
||
if (!previewImage) return null; | ||
|
||
return ( | ||
<div className="flex justify-between flex-wrap mt-5 relative"> | ||
<img | ||
src={previewImage} | ||
width={120} | ||
height={120} | ||
alt="Preview" | ||
className="rounded-full" | ||
/> | ||
<button | ||
className="w-36 h-10 self-end flex items-center gap-2 justify-center rounded-md text-white bg-red-700 hover:bg-red-500" | ||
onClick={deletePreviewImage} | ||
> | ||
<CiImageOff size={22}/> | ||
Delete Profile | ||
</button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ImagePreview; |
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,36 @@ | ||
import { useState, useEffect, useCallback } from "react"; | ||
import { UseFormReturn } from "react-hook-form"; | ||
import { | ||
handleFilePreview, | ||
handleImageUpload, | ||
} from "../../utils/imageuploadUtil"; | ||
import { TuserSchema } from "../../utils/userSchema"; | ||
|
||
const DEFAULT_IMAGE = | ||
"https://t4.ftcdn.net/jpg/01/24/65/69/360_F_124656969_x3y8YVzvrqFZyv3YLWNo6PJaC88SYxqM.jpg"; | ||
|
||
const useImageUpload = (form: UseFormReturn<TuserSchema>) => { | ||
const [previewImage, setPreviewImage] = useState<string | null>(null); | ||
const [isUploading, setIsUploading] = useState(false); | ||
const { setValue, watch } = form; | ||
const currentPicture = watch("picture"); | ||
|
||
useEffect(() => { | ||
setPreviewImage(currentPicture || DEFAULT_IMAGE); | ||
}, [currentPicture]); | ||
|
||
const handleImageChange = useCallback( | ||
(e: React.ChangeEvent<HTMLInputElement>) => { | ||
const file = e.target.files?.[0]; | ||
if (file) { | ||
handleFilePreview(file, setPreviewImage); | ||
handleImageUpload(file, setValue, setIsUploading); | ||
} | ||
}, | ||
[setValue] | ||
); | ||
|
||
return { previewImage, isUploading, handleImageChange, DEFAULT_IMAGE }; | ||
}; | ||
|
||
export default useImageUpload; |
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
Oops, something went wrong.