-
Couldn't load subscription status.
- Fork 1
[WC-28, WC-162] - Implement Client/Chef profile page, Implement edit Client/Chef profile page + API connection #21
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
base: main
Are you sure you want to change the base?
Changes from all commits
5c774d2
cf29ee7
e91b52f
fa8c47f
5225ca9
932c689
4163eb1
9c7bb36
1edac71
793dfb8
7ac27e7
4029ac8
4fbda0f
5b4ea10
1227111
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,37 @@ | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
| /.pnp | ||
| .pnp.js | ||
| .yarn/install-state.gz | ||
|
|
||
| # testing | ||
| /coverage | ||
|
|
||
| # next.js | ||
| /.next/ | ||
| /out/ | ||
|
|
||
| # production | ||
| /build | ||
|
|
||
| # misc | ||
| .DS_Store | ||
| *.pem | ||
|
|
||
| # debug | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # local env files | ||
| .env*.local | ||
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
| next-env.d.ts | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
| /.pnp | ||
| .pnp.js | ||
| .yarn/install-state.gz | ||
|
|
||
| # testing | ||
| /coverage | ||
|
|
||
| # next.js | ||
| /.next/ | ||
| /out/ | ||
|
|
||
| # production | ||
| /build | ||
|
|
||
| # misc | ||
| .DS_Store | ||
| *.pem | ||
|
|
||
| # debug | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # local env files | ||
| .env*.local | ||
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
| next-env.d.ts | ||
| .env | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import Image from 'next/image' | ||
| import Link from 'next/link' | ||
|
|
||
| export default function Footer() { | ||
|
Comment on lines
+1
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider relocating the Footer component and adding TypeScript types This appears to be a shared component but is located in the chef-specific directory. Consider moving it to a shared/common components directory. Apply these changes:
+interface FooterProps {
+ className?: string;
+}
+
-export default function Footer() {
+export default function Footer({ className }: FooterProps) {
|
||
| const footer_elements = [ | ||
| 'About', | ||
| 'Terms & conditions', | ||
| 'Privacy Policy', | ||
| 'Contact', | ||
| ] | ||
|
Comment on lines
+5
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance footer navigation items with proper structure and links The footer elements should include proper links and be properly typed. Replace the simple array with a properly structured constant: - const footer_elements = [
- 'About',
- 'Terms & conditions',
- 'Privacy Policy',
- 'Contact',
- ]
+ const FOOTER_LINKS = [
+ { label: 'About', href: '/about' },
+ { label: 'Terms & conditions', href: '/terms' },
+ { label: 'Privacy Policy', href: '/privacy' },
+ { label: 'Contact', href: '/contact' },
+ ] as const;Then update the mapping: - {footer_elements.map((item, index) => (
- <ul
+ {FOOTER_LINKS.map(({ label, href }) => (
+ <Link
+ href={href}
key={index}
className="cursor-pointer hover:text-transparent bg-clip-text bg-gradient-to-t from-[#FE3511] to-[#F0725C]"
>
- {item}
- </ul>
+ {label}
+ </Link>
))}
|
||
| return ( | ||
| <div className="relative bg-white"> | ||
| <div className="flex justify-between w-full p-8 px-28"> | ||
| <div> | ||
| <Link href="/chef/video"> | ||
| <Image | ||
| src="/svg/WecookedLogo.svg" | ||
| alt="WeCooked Logo" | ||
| width={120} | ||
| height={120} | ||
| className="cursor-pointer" | ||
| /> | ||
| </Link> | ||
| </div> | ||
| <div className="flex gap-x-6"> | ||
| {footer_elements.map((item, index) => ( | ||
| <ul | ||
| key={index} | ||
| className="cursor-pointer hover:text-transparent bg-clip-text bg-gradient-to-t from-[#FE3511] to-[#F0725C]" | ||
| > | ||
| {item} | ||
| </ul> | ||
| ))} | ||
| </div> | ||
| <div className="flex items-center gap-x-3"> | ||
| <Link href="/"> | ||
| <Image | ||
| src="/svg/fb-ic.svg" | ||
| alt="Facebook icon" | ||
| width={25} | ||
| height={25} | ||
| className="cursor-pointer" | ||
| /> | ||
| </Link> | ||
| <Link href="/"> | ||
| <Image | ||
| src="/svg/tweet-ic.svg" | ||
| alt="twitter icon" | ||
| width={25} | ||
| height={25} | ||
| className="cursor-pointer" | ||
| /> | ||
| </Link> | ||
| <Link href="/"> | ||
| <Image | ||
| src="/svg/insta-ic.svg" | ||
| alt="instagram icon" | ||
| width={25} | ||
| height={25} | ||
| className="cursor-pointer" | ||
| /> | ||
| </Link> | ||
| <Link href="/"> | ||
| <Image | ||
| src="/svg/google-ic.svg" | ||
| alt="Google icon" | ||
| width={25} | ||
| height={25} | ||
| className="cursor-pointer" | ||
| /> | ||
| </Link> | ||
| </div> | ||
|
Comment on lines
+35
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor social media section to reduce duplication and add proper links The social media section contains duplicated code and placeholder links.
const SOCIAL_MEDIA = [
{ platform: 'Facebook', icon: '/svg/fb-ic.svg', href: process.env.NEXT_PUBLIC_FACEBOOK_URL },
{ platform: 'Twitter', icon: '/svg/tweet-ic.svg', href: process.env.NEXT_PUBLIC_TWITTER_URL },
{ platform: 'Instagram', icon: '/svg/insta-ic.svg', href: process.env.NEXT_PUBLIC_INSTAGRAM_URL },
{ platform: 'Google', icon: '/svg/google-ic.svg', href: process.env.NEXT_PUBLIC_GOOGLE_URL },
] as const;
- <div className="flex items-center gap-x-3">
- <Link href="/">
- <Image
- src="/svg/fb-ic.svg"
- alt="Facebook icon"
- width={25}
- height={25}
- className="cursor-pointer"
- />
- </Link>
- // ... repeated code for other platforms
- </div>
+ <div className="flex items-center gap-x-3">
+ {SOCIAL_MEDIA.map(({ platform, icon, href }) => (
+ <Link key={platform} href={href ?? '/'} target="_blank" rel="noopener noreferrer">
+ <Image
+ src={icon}
+ alt={`${platform} icon`}
+ width={25}
+ height={25}
+ className="cursor-pointer"
+ />
+ </Link>
+ ))}
+ </div> |
||
| </div> | ||
| <div className="flex justify-center pb-16"> | ||
| Copyright ©{new Date().getFullYear()} Wecooked | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
|
Comment on lines
+4
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve accessibility and semantic HTML structure The component needs improvements for better accessibility support.
- <div className="relative bg-white">
+ <footer role="contentinfo" aria-label="Site footer" className="relative bg-white">
// Update navigation
- <div className="flex gap-x-6">
+ <nav aria-label="Footer navigation" className="flex gap-x-6">
// Update social media section
- <div className="flex items-center gap-x-3">
+ <div className="flex items-center gap-x-3" aria-label="Social media links">
// Add to social media links
className="cursor-pointer focus:ring-2 focus:ring-offset-2 focus:ring-[#FE3511] focus:outline-none"
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -97,6 +97,46 @@ export default function CourseUpload() { | |||||
| setIsSubmitting(true) | ||||||
| setSubmitError(null) | ||||||
|
|
||||||
| const courseUploadData = [ | ||||||
| { | ||||||
| courseTitle: 'Masterbate British Cuisine', | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct the typo in The Apply this diff to fix the typo: - courseTitle: 'Masterbate British Cuisine',
+ courseTitle: 'Master British Cuisine',📝 Committable suggestion
Suggested change
|
||||||
| courseDetail: | ||||||
| 'Learn the secrets of British cuisine from Gordon Ramsay.', | ||||||
| coursePrice: 100, | ||||||
| courseCategory: 'Cooking', | ||||||
| courseVideoId: 1, | ||||||
| courseChefId: 1, | ||||||
| coursePackId: 'pack1', | ||||||
| courseVideoPath: 'test12345678.com', | ||||||
| courseIngredientPrice: 123456, | ||||||
| courseIngredientDetail: 'Pork,Pork,Pork,Pork', | ||||||
| courseImage: 'placeholderImage.com', | ||||||
| }, | ||||||
| ] | ||||||
| try { | ||||||
| const response = await fetch( | ||||||
| `${process.env.NEXT_PUBLIC_BACKEND_URL}/chef/upload`, | ||||||
| { | ||||||
| method: 'POST', | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| body: JSON.stringify(courseUploadData), | ||||||
| } | ||||||
| ) | ||||||
|
|
||||||
| if (response.ok) { | ||||||
| const responseData = await response.json() | ||||||
| console.log('Upload successful:', responseData) | ||||||
| } else { | ||||||
| const errorDetails = await response.json() // Optional: read error response | ||||||
| console.error('Failed to upload:', response.status, errorDetails) | ||||||
| } | ||||||
| } catch (error) { | ||||||
| console.error('Error submitting the form:', error) | ||||||
| } | ||||||
|
|
||||||
|
Comment on lines
+100
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor duplicate submission logic There is duplicate submission logic in the Consider refactoring the code to use the form data ( - const courseUploadData = [
- {
- courseTitle: 'Master British Cuisine',
- courseDetail:
- 'Learn the secrets of British cuisine from Gordon Ramsay.',
- coursePrice: 100,
- courseCategory: 'Cooking',
- courseVideoId: 1,
- courseChefId: 1,
- coursePackId: 'pack1',
- courseVideoPath: 'test12345678.com',
- courseIngredientPrice: 123456,
- courseIngredientDetail: 'Pork,Pork,Pork,Pork',
- courseImage: 'placeholderImage.com',
- },
- ]
try {
+ const courseData: CourseSubmission = {
+ courseName,
+ courseDetail,
+ courseCategory,
+ courseDietary,
+ coursePrice,
+ coursePackPrice,
+ courseIngredients,
+ videoUrl,
+ coverImageUrl,
+ bookmarks: bookmarks.map((b) => ({
+ title: b.title,
+ time: b.time,
+ timeStop: b.timeStop,
+ timeCountdown: b.timeCountdown,
+ })),
+ }
+
const response = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}/chef/upload`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
- body: JSON.stringify(courseUploadData),
+ body: JSON.stringify(courseData),
}
)
if (response.ok) {
const responseData = await response.json()
console.log('Upload successful:', responseData)
+ setSubmitSuccess(true)
+ resetForm()
} else {
const errorDetails = await response.json() // Optional: read error response
console.error('Failed to upload:', response.status, errorDetails)
}
} catch (error) {
console.error('Error submitting the form:', error)
+ setSubmitError(error instanceof Error ? error.message : 'Unknown error')
} finally {
setIsSubmitting(false)
}
- try {
- const response = await mockSubmitToAPI(courseData)
- if (response.success) {
- setSubmitSuccess(true)
- // Reset form or navigate away
- resetForm()
- } else {
- throw new Error(response.message || 'Course submission failed')
- }
- } catch (error) {
- setSubmitError(error instanceof Error ? error.message : 'Unknown error')
- } finally {
- setIsSubmitting(false)
- }
|
||||||
|
|
||||||
| try { | ||||||
| const courseData: CourseSubmission = { | ||||||
| courseName, | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ import { AuthContext, useAuthContext } from '@/app/contexts/authcontext' | |||||||||||||||||
| import { useForm } from 'react-hook-form' | ||||||||||||||||||
| import { z } from 'zod' | ||||||||||||||||||
| import { zodResolver } from '@hookform/resolvers/zod' | ||||||||||||||||||
| import Cookies from 'js-cookie' | ||||||||||||||||||
|
|
||||||||||||||||||
| // Define the validation schema | ||||||||||||||||||
| const loginSchema = z.object({ | ||||||||||||||||||
|
|
@@ -56,19 +57,49 @@ export default function Login() { | |||||||||||||||||
| const login = () => { | ||||||||||||||||||
| setIsAuthenticated(true) | ||||||||||||||||||
| router.push('/chef/course') | ||||||||||||||||||
| if (remember == true && typeof window !== 'undefined') { | ||||||||||||||||||
| // Access localStorage here (to prevent netlify approvement fail) | ||||||||||||||||||
| localStorage.setItem('isAuthenticated', 'true') | ||||||||||||||||||
| if (remember) { | ||||||||||||||||||
| // Store authentication state in cookies | ||||||||||||||||||
| Cookies.set('Authorization', 'true', { expires: 7 }) // expires in 7 days if "Remember me" is checked | ||||||||||||||||||
| } else { | ||||||||||||||||||
|
|
||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const togglePasswordVisibility = () => setShowPassword((prev) => !prev) | ||||||||||||||||||
| const toggleRemember = () => setRemember((prev) => !prev) | ||||||||||||||||||
|
|
||||||||||||||||||
| // Update handleFormSubmit to handle form data | ||||||||||||||||||
| const handleFormSubmit = (data: LoginFormData) => { | ||||||||||||||||||
| console.log(JSON.stringify(data)) // Placeholder for auth logic | ||||||||||||||||||
| login() //set login state to true | ||||||||||||||||||
| const handleFormSubmit = async (data: LoginFormData) => { | ||||||||||||||||||
|
|
||||||||||||||||||
| const chefLoginData = [{ | ||||||||||||||||||
| chefEmail: data.email, | ||||||||||||||||||
| chefPassword: data.password, | ||||||||||||||||||
| }] | ||||||||||||||||||
|
Comment on lines
+74
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix incorrect API request payload structure The Modify the data structure: - const chefLoginData = [{
+ const chefLoginData = {
chefEmail: data.email,
chefPassword: data.password,
- }]
+ }📝 Committable suggestion
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| try { | ||||||||||||||||||
| const response = await fetch( | ||||||||||||||||||
| `${process.env.NEXT_PUBLIC_BACKEND_URL}/chef/login`, | ||||||||||||||||||
| { | ||||||||||||||||||
| method: 'POST', | ||||||||||||||||||
| headers: { | ||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||
| }, | ||||||||||||||||||
| body: JSON.stringify(chefLoginData), | ||||||||||||||||||
| } | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!response.ok) { | ||||||||||||||||||
| throw new Error('Login failed') | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const responseData = await response.json() | ||||||||||||||||||
| console.log('token received:', responseData.token) | ||||||||||||||||||
| Cookies.set('Authorization', responseData.token) | ||||||||||||||||||
|
|
||||||||||||||||||
| login() // Redirect to the home page | ||||||||||||||||||
| } catch (error) { | ||||||||||||||||||
| console.error('Login failed:', error) | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
|
|
@@ -184,7 +215,7 @@ export default function Login() { | |||||||||||||||||
| <div className="flex justify-center mt-6 gap-x-1 text-sm"> | ||||||||||||||||||
| <p>Don't have an account?</p> | ||||||||||||||||||
| <Link | ||||||||||||||||||
| href="/client/sign-up" | ||||||||||||||||||
| href="/chef/sign-up-chef" | ||||||||||||||||||
| className="cursor-pointer text-transparent bg-clip-text bg-gradient-to-t from-[#FE3511] to-[#F0725C] hover:underline font-medium" | ||||||||||||||||||
| > | ||||||||||||||||||
| Sign up now | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Environment variables need documentation and a template file
The codebase uses several environment variables but lacks documentation and a template:
NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESETfor file uploadsNEXT_PUBLIC_BACKEND_URLfor API endpointsAction items:
.env.examplefile listing all required variables🔗 Analysis chain
LGTM! Verify environment variable documentation exists.
Good practice to ignore
.envfiles to prevent accidental commit of sensitive data.Let's verify if proper documentation exists for the required environment variables:
Let me try searching for any
.env.exampleor similar template files that might document the environment variables.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 209
Script:
Length of output: 4078