diff --git a/package.json b/package.json index 73f9a19..4845043 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "react-dom": "19.0.0", "react-icons": "5.4.0", "tailwind-merge": "2.6.0", - "tailwindcss-animate": "1.0.7" + "tailwindcss-animate": "1.0.7", + "zod": "3.24.1" }, "devDependencies": { "@commitlint/cli": "19.6.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a7245e..bc26c96 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: tailwindcss-animate: specifier: 1.0.7 version: 1.0.7(tailwindcss@3.4.17) + zod: + specifier: 3.24.1 + version: 3.24.1 devDependencies: '@commitlint/cli': specifier: 19.6.1 @@ -2634,6 +2637,9 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + snapshots: '@alloc/quick-lru@5.2.0': {} @@ -5406,3 +5412,5 @@ snapshots: yocto-queue@0.1.0: {} yocto-queue@1.1.1: {} + + zod@3.24.1: {} diff --git a/src/app/(learners)/setting/page.tsx b/src/app/(learners)/setting/page.tsx new file mode 100644 index 0000000..43e114b --- /dev/null +++ b/src/app/(learners)/setting/page.tsx @@ -0,0 +1,29 @@ +import ProfileSettings from '@/components/learners/settings/ProfileSettings'; + +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +export default function Home() { + return ( +
+ +
+ ); +} diff --git a/src/components/commons/learners/NavigationBar.tsx b/src/components/commons/learners/NavigationBar.tsx new file mode 100644 index 0000000..1e1f0a0 --- /dev/null +++ b/src/components/commons/learners/NavigationBar.tsx @@ -0,0 +1,83 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import React from 'react'; + +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ + +export default function NavigationBar() { + const pathname = usePathname(); + const navItems = [ + { label: 'Dashboard', path: '/dashboard' }, + { label: 'Courses', path: '/courses' }, + { label: 'Teachers', path: '/teachers' }, + { label: 'Message', path: '/message' }, + { label: 'Wishlist', path: '/wishlist' }, + { label: 'Purchase History', path: '/purchase-history' }, + { label: 'Settings', path: '/setting' }, + ]; + + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/commons/learners/Profile.tsx b/src/components/commons/learners/Profile.tsx new file mode 100644 index 0000000..07c7fee --- /dev/null +++ b/src/components/commons/learners/Profile.tsx @@ -0,0 +1,62 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +import Image from 'next/image'; + +export default function Profile() { + return ( +
+
+
+
+ Lazy Code Logo +
+

Lazy Code

+

+ Web Designer & Best-Selling Instructor +

+
+ +
+
+
+
+ ); +} diff --git a/src/components/learners/settings/PasswordChangeForm.tsx b/src/components/learners/settings/PasswordChangeForm.tsx new file mode 100644 index 0000000..7006b96 --- /dev/null +++ b/src/components/learners/settings/PasswordChangeForm.tsx @@ -0,0 +1,130 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +import { ZodError, z } from 'zod'; + +const passwordSchema = z + .object({ + currentPassword: z.string().min(1, 'Current password is required.'), + newPassword: z + .string() + .min(6, 'New password must be at least 6 characters long.'), + confirmPassword: z.string(), + }) + .refine((data) => data.newPassword === data.confirmPassword, { + message: 'Passwords do not match.', + path: ['confirmPassword'], + }); + +export default function PasswordChangeForm() { + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const formData = new FormData(e.currentTarget); + const currentPassword = formData.get('currentPassword') as string; + const newPassword = formData.get('newPassword') as string; + const confirmPassword = formData.get('confirmPassword') as string; + + try { + passwordSchema.parse({ currentPassword, newPassword, confirmPassword }); + console.log('Form submitted successfully:', { + currentPassword, + newPassword, + confirmPassword, + }); + } catch (err) { + if (err instanceof ZodError) { + alert(err.errors[0].message); + } + } + }; + + return ( +
+ {/* Current Password */} +
+ +
+ +
+
+ + {/* New Password */} +
+ +
+ +
+
+ + {/* Confirm Password */} +
+ +
+ +
+
+ + {/* Submit Button */} + +
+ ); +} diff --git a/src/components/learners/settings/ProfileForm.tsx b/src/components/learners/settings/ProfileForm.tsx new file mode 100644 index 0000000..2f3200a --- /dev/null +++ b/src/components/learners/settings/ProfileForm.tsx @@ -0,0 +1,151 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +import { ZodError, z } from 'zod'; + +// Schema validation using Zod +const profileSchema = z.object({ + firstName: z.string().min(1, 'First name is required.'), + lastName: z.string().min(1, 'Last name is required.'), + username: z.string().min(1, 'Username is required.'), + email: z.string().email('Invalid email address.'), + title: z.string().max(50, 'Title must be 50 characters or less.'), +}); + +export default function ProfileForm() { + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const formData = new FormData(e.currentTarget); + const firstName = formData.get('firstName') as string; + const lastName = formData.get('lastName') as string; + const username = formData.get('username') as string; + const email = formData.get('email') as string; + const title = formData.get('title') as string; + + try { + profileSchema.parse({ firstName, lastName, username, email, title }); + console.log('Form submitted successfully:', { + firstName, + lastName, + username, + email, + title, + }); + } catch (err) { + if (err instanceof ZodError) { + alert(err.errors[0].message); + } + } + }; + + return ( +
+
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + + Max 50 characters + +
+
+ + +
+ ); +} diff --git a/src/components/learners/settings/ProfilePhotoUploader.tsx b/src/components/learners/settings/ProfilePhotoUploader.tsx new file mode 100644 index 0000000..971d815 --- /dev/null +++ b/src/components/learners/settings/ProfilePhotoUploader.tsx @@ -0,0 +1,52 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +import Image from 'next/image'; + +export default function ProfilePhotoUploader() { + return ( +
+
+ Profile + +
+

+ Image size should be under 1MB and image ratio needs to be 1:1 +

+
+ ); +} diff --git a/src/components/learners/settings/ProfileSettings.tsx b/src/components/learners/settings/ProfileSettings.tsx new file mode 100644 index 0000000..b06e3ef --- /dev/null +++ b/src/components/learners/settings/ProfileSettings.tsx @@ -0,0 +1,83 @@ +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ +'use client'; + +import NavigationBar from '../../commons/learners/NavigationBar'; +import Profile from '../../commons/learners/Profile'; +import React from 'react'; + +import PasswordChangeForm from './PasswordChangeForm'; +import ProfileForm from './ProfileForm'; +import ProfilePhotoUploader from './ProfilePhotoUploader'; + +/* + * ====================================================================== + * Copyright (C) 2025 - lzaycoe (Lazy Code) + * ====================================================================== + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ====================================================================== + */ + +export default function ProfileSettings() { + return ( +
+ {/* Profile Header */} + + + {/* Navigation */} + + + {/* Main Content */} +
+

Account settings

+ +
+ {/* Left Column - Photo Uploader */} + + + {/* Right Column - Forms */} +
+ + + {/* Password Change Section */} +
+

Change password

+ +
+
+
+
+
+ ); +}