From 24ab1f0d6361b9d300cae7db75577776120a1ebd Mon Sep 17 00:00:00 2001 From: Ifeoma Date: Tue, 24 Dec 2024 08:13:49 +0100 Subject: [PATCH 1/5] general settings --- app/(dashboard)/assets/imagecase.svg | 6 + .../settings/_components/EditBusiness.tsx | 200 ++++++++++++++++++ .../settings/_components/EditInformation.tsx | 186 ++++++++++++++++ .../settings/_components/General.tsx | 107 ++++++++++ .../settings/_components/Password.tsx | 7 + .../settings/_components/Permission.tsx | 7 + .../settings/_components/SettingsNavbar.tsx | 56 +++++ .../settings/_components/Staff.tsx | 7 + app/(dashboard)/settings/page.tsx | 39 +++- components/ui/alert-dialog.tsx | 2 +- package-lock.json | 6 + package.json | 1 + types/types.ts | 17 ++ 13 files changed, 638 insertions(+), 3 deletions(-) create mode 100644 app/(dashboard)/assets/imagecase.svg create mode 100644 app/(dashboard)/settings/_components/EditBusiness.tsx create mode 100644 app/(dashboard)/settings/_components/EditInformation.tsx create mode 100644 app/(dashboard)/settings/_components/General.tsx create mode 100644 app/(dashboard)/settings/_components/Password.tsx create mode 100644 app/(dashboard)/settings/_components/Permission.tsx create mode 100644 app/(dashboard)/settings/_components/SettingsNavbar.tsx create mode 100644 app/(dashboard)/settings/_components/Staff.tsx diff --git a/app/(dashboard)/assets/imagecase.svg b/app/(dashboard)/assets/imagecase.svg new file mode 100644 index 0000000..4ee65eb --- /dev/null +++ b/app/(dashboard)/assets/imagecase.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/(dashboard)/settings/_components/EditBusiness.tsx b/app/(dashboard)/settings/_components/EditBusiness.tsx new file mode 100644 index 0000000..c56397c --- /dev/null +++ b/app/(dashboard)/settings/_components/EditBusiness.tsx @@ -0,0 +1,200 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from '@/components/ui/alert-dialog'; +import { Button } from '@/components/ui/button'; +import { Calendar } from '@/components/ui/calendar'; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from '@/components/ui/popover'; + +import { cn } from '@/lib/utils'; +import { BusinessFormData } from '@/types/types'; +import { format } from 'date-fns'; +import { CalendarIcon, Pen } from 'lucide-react'; +import Image from 'next/image'; +import React, { useState } from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; + +type EditBusinessProps = { + onSubmit: (data: FieldValues) => void; +}; + +const EditBusiness = ({ onSubmit }: EditBusinessProps) => { + const [date, setDate] = useState(); + const [imageName, setImageName] = useState(''); + const [businessImage, setBusinessImage] = useState(null); + const { register, handleSubmit, watch } = useForm(); + + const nameValue = watch( + // 'businessPhoto' + 'businessName' + // 'memberSince', + // 'employeeNo' + ); + + const handleOnSubmit = (data: FieldValues) => { + data.businessPhoto = businessImage; + data.memberSince = date; + onSubmit(data); + console.log(data); + }; + + const handleImageUpload = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + setImageName(file.name); + setBusinessImage(URL.createObjectURL(file)); // Generate local preview URL + } + }; + + return ( + + + + + + + + +
+
+
+ {businessImage ? ( +
+ {imageName} +
+ ) : ( +
+ + +
+ )} +
+
+
+ + +
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+ + Cancel + + + Save Changes + +
+
+
+
+
+
+ ); +}; + +export default EditBusiness; diff --git a/app/(dashboard)/settings/_components/EditInformation.tsx b/app/(dashboard)/settings/_components/EditInformation.tsx new file mode 100644 index 0000000..a4a3732 --- /dev/null +++ b/app/(dashboard)/settings/_components/EditInformation.tsx @@ -0,0 +1,186 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from '@/components/ui/alert-dialog'; +import { InformationFormData } from '@/types/types'; +import { Pen } from 'lucide-react'; +import React from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; + +type EditInformationProps = { + onSubmit: (data: FieldValues) => void; +}; + +const EditInformation = ({ onSubmit }: EditInformationProps) => { + const { register, handleSubmit, reset } = useForm(); + + const handleOnSubmit = (data: FieldValues) => { + onSubmit(data); + console.log(data); + reset(); + }; + + return ( + + + + + + + + +
+
+

Information

+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ +
+ + Cancel + + + Save Changes + +
+
+
+
+
+
+ ); +}; + +export default EditInformation; diff --git a/app/(dashboard)/settings/_components/General.tsx b/app/(dashboard)/settings/_components/General.tsx new file mode 100644 index 0000000..7e66ba1 --- /dev/null +++ b/app/(dashboard)/settings/_components/General.tsx @@ -0,0 +1,107 @@ +import React, { useState } from 'react'; +import EditBusiness from './EditBusiness'; +import EditInformation from './EditInformation'; +import { BusinessFormData, InformationFormData } from '@/types/types'; +import Image from 'next/image'; +import ImageCase from '@/app/(dashboard)/assets/imagecase.svg'; + +const General = () => { + const [businessData, setBusinessData] = useState( + null + ); + const [informationData, setInformationData] = + useState(null); + + const handleBusinessSubmit = (data: any) => { + setBusinessData(data); + }; + + const handleInformationSubmit = (data: any) => { + setInformationData(data); + }; + + return ( +
+
+
+
+ business photo + +
+

+ {businessData?.businessName || '[Business Name]'} +

+ + +
+
+
+ +
+
+ +
+
+
+

Information

+ +
+
+
+
+

Email:

+

{informationData?.email || null}

+
+
+

Phone Number:

+

{informationData?.phoneNumber || null}

+
+
+

BVN:

+

{informationData?.bvn || null}

+
+
+
+
+

Address Line 1:

+

{informationData?.addressLine1 || null}

+
+
+

Address Line 2:

+

{informationData?.addressLine2 || null}

+
+
+
+
+

Country:

+

{informationData?.country || null}

+
+
+

City:

+

{informationData?.city || null}

+
+
+

Postal Code:

+

{informationData?.postalCode || null}

+
+
+
+
+
+
+
+ ); +}; + +export default General; diff --git a/app/(dashboard)/settings/_components/Password.tsx b/app/(dashboard)/settings/_components/Password.tsx new file mode 100644 index 0000000..9c791e6 --- /dev/null +++ b/app/(dashboard)/settings/_components/Password.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const Password = () => { + return
Password
; +}; + +export default Password; diff --git a/app/(dashboard)/settings/_components/Permission.tsx b/app/(dashboard)/settings/_components/Permission.tsx new file mode 100644 index 0000000..8a5d1bc --- /dev/null +++ b/app/(dashboard)/settings/_components/Permission.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const Permission = () => { + return
Permission
; +}; + +export default Permission; diff --git a/app/(dashboard)/settings/_components/SettingsNavbar.tsx b/app/(dashboard)/settings/_components/SettingsNavbar.tsx new file mode 100644 index 0000000..3ead2f0 --- /dev/null +++ b/app/(dashboard)/settings/_components/SettingsNavbar.tsx @@ -0,0 +1,56 @@ +import classNames from 'classnames'; +import React from 'react'; + +type Props = { + handleClickSettings: (item: string) => void; + selectedSetting: string; +}; + +const SettingsNavbar = ({ handleClickSettings, selectedSetting }: Props) => { + const settingsNavbar = [ + { + key: 'general', + text: 'General', + }, + { + key: 'staff', + text: 'Staff', + }, + { + key: 'permission', + text: 'Permission', + }, + { + key: 'password', + text: 'Password', + }, + ]; + + return ( +
+
+ {settingsNavbar.map(({ key, text }) => { + const isActive = selectedSetting === key; + + return ( + handleClickSettings(key)} + key={key} + className={classNames( + `hover:bg-[#DEE4FF] py-2 px-[18px] rounded-[20px] cursor-pointer relative text-xs`, + { + 'bg-[#DEE4FF] font-semibold text-[#0F172A] active': isActive, + }, + { 'bg-transparent text-[#475569]': !isActive } + )} + > + {text} + + ); + })} +
+
+ ); +}; + +export default SettingsNavbar; diff --git a/app/(dashboard)/settings/_components/Staff.tsx b/app/(dashboard)/settings/_components/Staff.tsx new file mode 100644 index 0000000..7280c4d --- /dev/null +++ b/app/(dashboard)/settings/_components/Staff.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const Staff = () => { + return
Staff
; +}; + +export default Staff; diff --git a/app/(dashboard)/settings/page.tsx b/app/(dashboard)/settings/page.tsx index ceb90fc..663347f 100644 --- a/app/(dashboard)/settings/page.tsx +++ b/app/(dashboard)/settings/page.tsx @@ -1,7 +1,42 @@ -import React from 'react'; +'use client'; +import React, { useState } from 'react'; +import General from './_components/General'; +import Staff from './_components/Staff'; +import Password from './_components/Password'; +import Permission from './_components/Permission'; +import SettingsNavbar from './_components/SettingsNavbar'; const Settings = () => { - return
Settings
; + const [selectedSettings, setSelectedSettings] = useState('general'); + + const handleCickSettings = (item: string) => { + setSelectedSettings(item); + }; + + const stepToRender = (key: string) => { + switch (key) { + case 'general': + return ; + case 'staff': + return ; + case 'permission': + return ; + case 'password': + return ; + default: + break; + } + }; + + return ( +
+ +
{stepToRender(selectedSettings)}
+
+ ); }; export default Settings; diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx index 5b558e4..b5c4585 100644 --- a/components/ui/alert-dialog.tsx +++ b/components/ui/alert-dialog.tsx @@ -36,7 +36,7 @@ const AlertDialogContent = React.forwardRef< Date: Mon, 20 Jan 2025 18:30:50 +0100 Subject: [PATCH 2/5] staff settings --- app/(dashboard)/assets/photocase.svg | 5 + .../settings/_components/AddStaff.tsx | 310 ++++++++++++++++++ .../settings/_components/SettingsNavbar.tsx | 4 +- .../settings/_components/Staff.tsx | 80 ++++- .../settings/_components/ToggleSwitch.tsx | 31 ++ components/Checkbox/Checkbox.tsx | 42 +++ components/DataTable/Export/Export.tsx | 12 +- components/SuccesModal/SuccesModal.tsx | 23 +- components/ui/sheet.tsx | 142 ++++++++ constants/tableData.tsx | 141 +++++++- package-lock.json | 160 +++++++-- package.json | 1 + 12 files changed, 909 insertions(+), 42 deletions(-) create mode 100644 app/(dashboard)/assets/photocase.svg create mode 100644 app/(dashboard)/settings/_components/AddStaff.tsx create mode 100644 app/(dashboard)/settings/_components/ToggleSwitch.tsx create mode 100644 components/Checkbox/Checkbox.tsx create mode 100644 components/ui/sheet.tsx diff --git a/app/(dashboard)/assets/photocase.svg b/app/(dashboard)/assets/photocase.svg new file mode 100644 index 0000000..7d566df --- /dev/null +++ b/app/(dashboard)/assets/photocase.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/(dashboard)/settings/_components/AddStaff.tsx b/app/(dashboard)/settings/_components/AddStaff.tsx new file mode 100644 index 0000000..1e81cda --- /dev/null +++ b/app/(dashboard)/settings/_components/AddStaff.tsx @@ -0,0 +1,310 @@ +import { + Sheet, + SheetClose, + SheetContent, + SheetTitle, + SheetTrigger, +} from '@/components/ui/sheet'; +import { CirclePlus } from 'lucide-react'; +import PhotoCase from '@/app/(dashboard)/assets/photocase.svg'; +import { ChangeEvent, useState } from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; +import Image from 'next/image'; +import Checkbox from '@/components/Checkbox/Checkbox'; +import SuccesModal from '@/components/SuccesModal/SuccesModal'; + +export function AddStaff() { + const [addImage, setAddImage] = useState(PhotoCase); + const [step, setStep] = useState('form'); + const { register, handleSubmit, watch } = useForm(); + + const handleOnSubmit = (data: FieldValues) => { + data.photo = addImage; + console.log(data); + }; + + const handleImageUpload = (event: ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + setAddImage(URL.createObjectURL(file)); + } + }; + + const handleDeleteImage = () => { + setAddImage(PhotoCase); + }; + + const nameValue = watch('password'); + + return ( + + + + + {step === 'form' ? ( + +
+
+ + Add New Staff + + +
+ {addImage && ( + staff name + )} +
+ + +
+
+

+ Delete +

+
+
+ +
+

+ Staff Information +

+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+

+ Security +

+
+
+ + +
+
+ + +
+
+
+ +
+

+ Access +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+ + Cancel + + + +
+
+
+
+ ) : ( + + + + )} +
+ ); +} diff --git a/app/(dashboard)/settings/_components/SettingsNavbar.tsx b/app/(dashboard)/settings/_components/SettingsNavbar.tsx index 3ead2f0..b3543b6 100644 --- a/app/(dashboard)/settings/_components/SettingsNavbar.tsx +++ b/app/(dashboard)/settings/_components/SettingsNavbar.tsx @@ -28,7 +28,7 @@ const SettingsNavbar = ({ handleClickSettings, selectedSetting }: Props) => { return (
-
+
{settingsNavbar.map(({ key, text }) => { const isActive = selectedSetting === key; @@ -37,7 +37,7 @@ const SettingsNavbar = ({ handleClickSettings, selectedSetting }: Props) => { onClick={() => handleClickSettings(key)} key={key} className={classNames( - `hover:bg-[#DEE4FF] py-2 px-[18px] rounded-[20px] cursor-pointer relative text-xs`, + `hover:bg-[#DEE4FF] py-1 sm:py-2 px-3 sm:px-[18px] rounded-[20px] cursor-pointer relative text-xs`, { 'bg-[#DEE4FF] font-semibold text-[#0F172A] active': isActive, }, diff --git a/app/(dashboard)/settings/_components/Staff.tsx b/app/(dashboard)/settings/_components/Staff.tsx index 7280c4d..576ac51 100644 --- a/app/(dashboard)/settings/_components/Staff.tsx +++ b/app/(dashboard)/settings/_components/Staff.tsx @@ -1,7 +1,85 @@ +import { DataTable } from '@/components/DataTable/DataTable'; +import Export from '@/components/DataTable/Export/Export'; +import FilterBtn from '@/components/DataTable/Filter/Filter'; +import Refresh from '@/components/DataTable/Refresh/Refresh'; +import SearchBar from '@/components/DataTable/Search/Search'; +import { staffSettingsColumn, staffSettingsData } from '@/constants/tableData'; import React from 'react'; +import { AddStaff } from './AddStaff'; const Staff = () => { - return
Staff
; + return ( +
+
+
+
+
+
+

Email:

+

user@paystride.com

+
+
+

Phone Number:

+

+234 201 *** ****

+
+
+

BVN:

+

0000 000 0000

+
+
+
+
+

Address Line 1:

+

+ 14 Idowu Martins Street, Victoria Island +

+
+
+
+ +
+
+

Country:

+

Nigeria

+
+
+

City:

+

Lagos

+
+
+

Postal Code:

+

105102

+
+
+
+
+ +
+
+
+ +
+ + +
+
+
+ + +
+
+
+ +
+
+
+ ); }; export default Staff; diff --git a/app/(dashboard)/settings/_components/ToggleSwitch.tsx b/app/(dashboard)/settings/_components/ToggleSwitch.tsx new file mode 100644 index 0000000..3ed2f9a --- /dev/null +++ b/app/(dashboard)/settings/_components/ToggleSwitch.tsx @@ -0,0 +1,31 @@ +import React, { useState } from 'react'; + +type ToggleProps = { + isOn: boolean; + // onToggle: () => void; +}; + +const ToggleSwitch = ({ isOn }: ToggleProps) => { + const [toggleState, setToggleState] = useState(isOn); + + const handleToggle = () => { + setToggleState(!toggleState); + }; + + return ( +
e.key === 'Enter' && handleToggle()} + > +
+
+ ); +}; + +export default ToggleSwitch; diff --git a/components/Checkbox/Checkbox.tsx b/components/Checkbox/Checkbox.tsx new file mode 100644 index 0000000..335b03a --- /dev/null +++ b/components/Checkbox/Checkbox.tsx @@ -0,0 +1,42 @@ +import { Check } from 'lucide-react'; +import React, { useState } from 'react'; + +interface CheckboxProps { + label: string; + register: any; +} + +const Checkbox = ({ label, register }: CheckboxProps) => { + const [checked, setChecked] = useState(false); + + const handleToggle = () => { + setChecked(!checked); + }; + + return ( +
+ + + + + {label} +
+ ); +}; + +export default Checkbox; diff --git a/components/DataTable/Export/Export.tsx b/components/DataTable/Export/Export.tsx index eb5790d..ea9cf10 100644 --- a/components/DataTable/Export/Export.tsx +++ b/components/DataTable/Export/Export.tsx @@ -1,13 +1,19 @@ import { CloudDownload } from 'lucide-react'; import React from 'react'; -const Export = () => { +type ExportProps = { + iconColor?: string; + btnColor?: React.CSSProperties; +}; + +const Export = ({ iconColor, btnColor }: ExportProps) => { return ( ); diff --git a/components/SuccesModal/SuccesModal.tsx b/components/SuccesModal/SuccesModal.tsx index d98b07b..4647b78 100644 --- a/components/SuccesModal/SuccesModal.tsx +++ b/components/SuccesModal/SuccesModal.tsx @@ -2,14 +2,21 @@ import React from 'react'; import successIcon from '@/app/assets/successIcon.svg'; import Image from 'next/image'; import { AlertDialogCancel } from '@/components/ui/alert-dialog'; +import { SheetClose } from '../ui/sheet'; type SuccessModalProp = { title?: string; close: string; message: string; + closeContent?: string; }; -const SuccesModal = ({ title, message, close }: SuccessModalProp) => { +const SuccesModal = ({ + title, + message, + close, + closeContent, +}: SuccessModalProp) => { return (
@@ -22,12 +29,18 @@ const SuccesModal = ({ title, message, close }: SuccessModalProp) => { height={120} className="w-24 sm:w-[120px]" /> - + {message} - - {close} - + {closeContent === 'sheet' ? ( + + {close} + + ) : ( + + {close} + + )}
diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx new file mode 100644 index 0000000..52e7888 --- /dev/null +++ b/components/ui/sheet.tsx @@ -0,0 +1,142 @@ +'use client'; + +import * as React from 'react'; +import * as SheetPrimitive from '@radix-ui/react-dialog'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { X } from 'lucide-react'; + +import { cn } from '@/lib/utils'; + +const Sheet = SheetPrimitive.Root; + +const SheetTrigger = SheetPrimitive.Trigger; + +const SheetClose = SheetPrimitive.Close; + +const SheetPortal = SheetPrimitive.Portal; + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; + +const sheetVariants = cva( + 'fixed z-50 gap-4 bg-background rounded-[20px] p-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out', + { + variants: { + side: { + top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top', + bottom: + 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom', + left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm', + right: + 'inset-y-0 right-0 h-full w-5/6 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm', + center: + 'grid min-w-[88%] sm:min-w-[384px] translate-x-[-50%] md:translate-x-[calc(-50%+21rem)] translate-y-[-50%] top-[50%] left-[50%] md:left-[calc(50%-14rem)] rounded-[20px] !duration-0 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', + }, + }, + defaultVariants: { + side: 'right', + }, + } +); + +interface SheetContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + SheetContentProps +>(({ side = 'right', className, children, ...props }, ref) => ( + + + + + + Close + + {children} + + +)); +SheetContent.displayName = SheetPrimitive.Content.displayName; + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +SheetHeader.displayName = 'SheetHeader'; + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +SheetFooter.displayName = 'SheetFooter'; + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetTitle.displayName = SheetPrimitive.Title.displayName; + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetDescription.displayName = SheetPrimitive.Description.displayName; + +export { + Sheet, + SheetPortal, + SheetOverlay, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +}; diff --git a/constants/tableData.tsx b/constants/tableData.tsx index 4f2b399..faad655 100644 --- a/constants/tableData.tsx +++ b/constants/tableData.tsx @@ -1,6 +1,6 @@ 'use client'; import { ColumnDef } from '@tanstack/react-table'; -import { ChevronsUpDown } from 'lucide-react'; +import { ChevronsUpDown, Pencil, Trash2 } from 'lucide-react'; import Corey from '@/app/(dashboard)/assets/corey.svg'; import Kaiya from '@/app/(dashboard)/assets/kaiya.jpg'; import SalesName from '@/components/DataTable/SalesName/SalesName'; @@ -8,6 +8,7 @@ import DateTime from '@/components/DataTable/DateTime/DateTime'; import TableStatus from '@/components/DataTable/TableSatus/TableStatus'; import TableMethod from '@/components/DataTable/TableMethod/TableMethod'; import EditModal from '@/app/(dashboard)/payment-point/_component/EditModal'; +import ToggleSwitch from '@/app/(dashboard)/settings/_components/ToggleSwitch'; type SalesData = { name: string; @@ -48,6 +49,14 @@ type SettlementsData = { bank: string; amount: string; }; +type StaffSettingsData = { + name: string; + image: string | any; + phone: string; + role: string; + department: string; + action: boolean; +}; export const salesData: SalesData[] = [ { @@ -515,3 +524,133 @@ export const settlementsColumn: ColumnDef[] = [ header: () =>
Amount
, }, ]; + +export const staffSettingsData: StaffSettingsData[] = [ + { + name: 'Corey Carder', + image: Corey, + phone: '08123231212', + role: 'Cashier', + department: 'Sales', + action: true, + }, + { + name: 'Kaiya Batista', + image: Kaiya, + phone: '08122222222', + role: 'Cashier', + department: 'Sales', + action: true, + }, + { + name: 'Charlie Lucatero', + image: Corey, + phone: '08178231213', + role: 'Sales Manager', + department: 'Sales', + action: true, + }, + { + name: 'Karla Bosco', + image: Corey, + phone: '9225433854', + role: 'Operation Manager', + department: 'Sales', + action: false, + }, + { + name: 'Kiera Herwitz', + image: Corey, + phone: '07011111111', + role: 'Sales Manager', + department: 'Sales', + action: false, + }, + { + name: 'Brandon Goyette', + image: Corey, + phone: '8254502917', + role: 'Operation Managerr', + department: 'Sales', + action: false, + }, +]; + +export const staffSettingsColumn: ColumnDef[] = [ + { + accessorKey: 'name', + header: ({ column }) => ( +
+ +
+ ), + cell: ({ row }) => ( + + ), + }, + { + accessorKey: 'role', + header: () => ( +
Role
+ ), + }, + { + accessorKey: 'department', + header: () => ( +
+ Department +
+ ), + cell: ({ row }) => ( +
{row.original.department}
+ ), + }, + { + accessorKey: 'action', + header: () => ( +
+ Action +
+ ), + cell: ({ row }) => ( +
+ +
+ ), + }, + { + id: 'edit', + header: () => ( +
+ Edit +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, + { + id: 'removeStaff', + header: () => ( +
+ Remove Staff +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, +]; diff --git a/package-lock.json b/package-lock.json index c35dfa0..4324d3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@hookform/resolvers": "^3.9.1", "@radix-ui/react-accordion": "^1.2.1", "@radix-ui/react-alert-dialog": "^1.1.3", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-popover": "^1.1.3", "@radix-ui/react-slot": "^1.1.1", "@tanstack/react-table": "^8.20.5", @@ -597,6 +598,64 @@ } } }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dialog": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.3.tgz", + "integrity": "sha512-ujGvqQNkZ0J7caQyl8XuZRj2/TIrYcOGwqz5TeD1OMcCdfBuEMP0D12ve+8J5F9XuNUth3FAKFWo/wt0E/GJrQ==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.2", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-primitive": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", @@ -782,14 +841,14 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.3.tgz", - "integrity": "sha512-ujGvqQNkZ0J7caQyl8XuZRj2/TIrYcOGwqz5TeD1OMcCdfBuEMP0D12ve+8J5F9XuNUth3FAKFWo/wt0E/GJrQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.3", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.1", "@radix-ui/react-id": "1.1.0", @@ -799,7 +858,7 @@ "@radix-ui/react-slot": "1.1.1", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" + "react-remove-scroll": "^2.6.1" }, "peerDependencies": { "@types/react": "*", @@ -835,6 +894,32 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", @@ -880,6 +965,30 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz", + "integrity": "sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -3963,14 +4072,6 @@ "node": ">= 0.4" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -5815,19 +5916,19 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", - "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "dependencies": { - "react-style-singleton": "^2.2.1", + "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -5836,20 +5937,19 @@ } }, "node_modules/react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", "dependencies": { "get-nonce": "^1.0.0", - "invariant": "^2.2.4", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -6885,9 +6985,9 @@ } }, "node_modules/use-callback-ref": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", - "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "dependencies": { "tslib": "^2.0.0" }, @@ -6895,8 +6995,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { diff --git a/package.json b/package.json index 1387643..362586d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@hookform/resolvers": "^3.9.1", "@radix-ui/react-accordion": "^1.2.1", "@radix-ui/react-alert-dialog": "^1.1.3", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-popover": "^1.1.3", "@radix-ui/react-slot": "^1.1.1", "@tanstack/react-table": "^8.20.5", From d6b9241f41c3a34be539ec3b97c8ce0b527b8461 Mon Sep 17 00:00:00 2001 From: Ifeoma Date: Mon, 20 Jan 2025 20:33:12 +0100 Subject: [PATCH 3/5] permission settings --- .../settings/_components/Permission.tsx | 34 ++++- components/Checkbox/Checkbox.tsx | 93 ++++++++---- constants/tableData.tsx | 132 +++++++++++++++++- 3 files changed, 232 insertions(+), 27 deletions(-) diff --git a/app/(dashboard)/settings/_components/Permission.tsx b/app/(dashboard)/settings/_components/Permission.tsx index 8a5d1bc..94bd67c 100644 --- a/app/(dashboard)/settings/_components/Permission.tsx +++ b/app/(dashboard)/settings/_components/Permission.tsx @@ -1,7 +1,39 @@ +import FilterBtn from '@/components/DataTable/Filter/Filter'; +import Refresh from '@/components/DataTable/Refresh/Refresh'; +import SearchBar from '@/components/DataTable/Search/Search'; import React from 'react'; +import { AddStaff } from './AddStaff'; +import Export from '@/components/DataTable/Export/Export'; +import { DataTable } from '@/components/DataTable/DataTable'; +import { permissionColumn, permissionData } from '@/constants/tableData'; const Permission = () => { - return
Permission
; + return ( +
+
+
+ +
+ + +
+
+
+ + +
+
+
+ +
+
+ ); }; export default Permission; diff --git a/components/Checkbox/Checkbox.tsx b/components/Checkbox/Checkbox.tsx index 335b03a..b48551e 100644 --- a/components/Checkbox/Checkbox.tsx +++ b/components/Checkbox/Checkbox.tsx @@ -2,11 +2,12 @@ import { Check } from 'lucide-react'; import React, { useState } from 'react'; interface CheckboxProps { - label: string; - register: any; + label?: string; + register?: any; + use?: string; } -const Checkbox = ({ label, register }: CheckboxProps) => { +const Checkbox = ({ label, register, use }: CheckboxProps) => { const [checked, setChecked] = useState(false); const handleToggle = () => { @@ -14,28 +15,70 @@ const Checkbox = ({ label, register }: CheckboxProps) => { }; return ( -
- - - - - {label} -
+ <> + {use === 'table' ? ( +
+ + + +
+ ) : ( +
+ + + + + {label} +
+ )} + + + //
+ // + + // + + // {label} + //
); }; diff --git a/constants/tableData.tsx b/constants/tableData.tsx index faad655..0d9189d 100644 --- a/constants/tableData.tsx +++ b/constants/tableData.tsx @@ -1,6 +1,6 @@ 'use client'; import { ColumnDef } from '@tanstack/react-table'; -import { ChevronsUpDown, Pencil, Trash2 } from 'lucide-react'; +import { Check, ChevronsUpDown, Pencil, Trash2 } from 'lucide-react'; import Corey from '@/app/(dashboard)/assets/corey.svg'; import Kaiya from '@/app/(dashboard)/assets/kaiya.jpg'; import SalesName from '@/components/DataTable/SalesName/SalesName'; @@ -9,6 +9,8 @@ import TableStatus from '@/components/DataTable/TableSatus/TableStatus'; import TableMethod from '@/components/DataTable/TableMethod/TableMethod'; import EditModal from '@/app/(dashboard)/payment-point/_component/EditModal'; import ToggleSwitch from '@/app/(dashboard)/settings/_components/ToggleSwitch'; +import Checkbox from '@/components/Checkbox/Checkbox'; +import { useState } from 'react'; type SalesData = { name: string; @@ -49,6 +51,7 @@ type SettlementsData = { bank: string; amount: string; }; + type StaffSettingsData = { name: string; image: string | any; @@ -58,6 +61,12 @@ type StaffSettingsData = { action: boolean; }; +type PermissionData = { + name: string; + image: string | any; + phone: string; +}; + export const salesData: SalesData[] = [ { name: 'Corey Carder', @@ -654,3 +663,124 @@ export const staffSettingsColumn: ColumnDef[] = [ ), }, ]; + +export const permissionData: PermissionData[] = [ + { + name: 'Corey Carder', + image: Corey, + phone: '08123231212', + }, + { + name: 'Kaiya Batista', + image: Kaiya, + phone: '08122222222', + }, + { + name: 'Charlie Lucatero', + image: Corey, + phone: '08178231213', + }, + { + name: 'Karla Bosco', + image: Corey, + phone: '9225433854', + }, + { + name: 'Kiera Herwitz', + image: Corey, + phone: '07011111111', + }, + { + name: 'Brandon Goyette', + image: Corey, + phone: '8254502917', + }, +]; + +export const permissionColumn: ColumnDef[] = [ + { + accessorKey: 'name', + header: ({ column }) => ( +
+ +
+ ), + cell: ({ row }) => ( + + ), + }, + { + id: 'dashboard', + header: () => ( +
+ Dashboard +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, + { + id: 'transaction', + header: () => ( +
+ Transaction +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, + { + id: 'payPoint', + header: () => ( +
+ PayPoint +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, + { + id: 'settlement', + header: () => ( +
+ Settlement +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, + { + id: 'settings', + header: () => ( +
+ Settings +
+ ), + cell: ({}) => ( +
+ +
+ ), + }, +]; From a101854715104dd8f82e37a4281bc24630161e13 Mon Sep 17 00:00:00 2001 From: Ifeoma Date: Wed, 22 Jan 2025 15:02:21 +0100 Subject: [PATCH 4/5] password settings --- .../settings/_components/ConfirmationCode.tsx | 118 ++++++++++++++++++ .../settings/_components/NewPassword.tsx | 59 +++++++++ .../settings/_components/Password.tsx | 39 +++++- .../settings/_components/PasswordReset.tsx | 59 +++++++++ .../settings/_components/ResetSuccessful.tsx | 33 +++++ 5 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 app/(dashboard)/settings/_components/ConfirmationCode.tsx create mode 100644 app/(dashboard)/settings/_components/NewPassword.tsx create mode 100644 app/(dashboard)/settings/_components/PasswordReset.tsx create mode 100644 app/(dashboard)/settings/_components/ResetSuccessful.tsx diff --git a/app/(dashboard)/settings/_components/ConfirmationCode.tsx b/app/(dashboard)/settings/_components/ConfirmationCode.tsx new file mode 100644 index 0000000..e3196ca --- /dev/null +++ b/app/(dashboard)/settings/_components/ConfirmationCode.tsx @@ -0,0 +1,118 @@ +import { Columns3 } from 'lucide-react'; +import { useRouter } from 'next/router'; +import React, { useRef, useState } from 'react'; +import { useForm } from 'react-hook-form'; + +type Props = { + nextPasswordStep: () => void; +}; + +const ConfirmationCode = ({ nextPasswordStep }: Props) => { + const [confirmationCode, setConfirmationCode] = useState( + Array(4).fill('') + ); + const { handleSubmit, clearErrors } = useForm(); + + const handleOnSubmit = () => { + const code = confirmationCode.join(''); + console.log('Confirmation code submitted:', code); + nextPasswordStep(); + }; + + const inputRefs = useRef<(HTMLInputElement | null)[]>([]); + + const handleChange = (index: number, value: string) => { + if (value.length > 1) { + value = value[0]; + } + const newConfirmationCode = [...confirmationCode]; + newConfirmationCode[index] = value; + setConfirmationCode(newConfirmationCode); + // Move to next input if value is entered + if (value && index < 5) { + inputRefs.current[index + 1]?.focus(); + } + // Clear any previous errors when user starts typing + clearErrors('code'); + }; + + const handleKeyDown = ( + index: number, + e: React.KeyboardEvent + ) => { + if (e.key === 'Backspace' && !confirmationCode[index] && index > 0) { + inputRefs.current[index - 1]?.focus(); + } + }; + + const handlePaste = (e: React.ClipboardEvent) => { + e.preventDefault(); + const pastedData = e.clipboardData.getData('text').slice(0, 6); + const newConfirmationCode = [...confirmationCode]; + + for (let i = 0; i < pastedData.length; i++) { + if (i < 6) { + newConfirmationCode[i] = pastedData[i]; + } + } + + setConfirmationCode(newConfirmationCode); + + // Focus the next empty input or the last input + const nextEmptyIndex = newConfirmationCode.findIndex((x) => !x); + if (nextEmptyIndex !== -1) { + inputRefs.current[nextEmptyIndex]?.focus(); + } else { + inputRefs.current[5]?.focus(); + } + }; + + const buttonDisabled = confirmationCode.some((digit) => digit === ''); + + return ( +
+
+ +
+
+

+ Enter confirmation code +

+

+ We've sent a code to{' '} + user@paystride.com +

+
+
+
+ {confirmationCode.map((digit, index) => ( + { + inputRefs.current[index] = el; + }} + type="text" + inputMode="numeric" + maxLength={1} + value={digit} + onChange={(e) => handleChange(index, e.target.value)} + onKeyDown={(e) => handleKeyDown(index, e)} + onPaste={handlePaste} + className="w-12 min-[375px]:w-16 sm:w-[90px] h-20 min-[375px]:h-24 sm:h-[120px] text-center text-[#0F172A] text-5xl font-semibold border border-[#CBD5E1] rounded-[10px] focus:border-[#324BC6] focus:outline-none" + aria-label={`Digit ${index + 1}`} + /> + ))} +
+ +
+
+ ); +}; + +export default ConfirmationCode; diff --git a/app/(dashboard)/settings/_components/NewPassword.tsx b/app/(dashboard)/settings/_components/NewPassword.tsx new file mode 100644 index 0000000..9207471 --- /dev/null +++ b/app/(dashboard)/settings/_components/NewPassword.tsx @@ -0,0 +1,59 @@ +import { LockKeyhole } from 'lucide-react'; +import { useRouter } from 'next/navigation'; +import React from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; + +type Props = { + nextPasswordStep: () => void; +}; + +const NewPassword = ({ nextPasswordStep }: Props) => { + const { register, handleSubmit, watch } = useForm(); + + const handleOnSubmit = (data: FieldValues) => { + nextPasswordStep(); + console.log(data); + }; + + const nameValue = watch('confirmNewPassword'); + + return ( +
+
+ +
+
+

+ Create new password +

+

+ Please create a password that's different from your previous + ones. It must be at least 4 digits. +

+
+
+ + + +
+
+ ); +}; + +export default NewPassword; diff --git a/app/(dashboard)/settings/_components/Password.tsx b/app/(dashboard)/settings/_components/Password.tsx index 9c791e6..7718b40 100644 --- a/app/(dashboard)/settings/_components/Password.tsx +++ b/app/(dashboard)/settings/_components/Password.tsx @@ -1,7 +1,42 @@ -import React from 'react'; +import React, { useState } from 'react'; +import PasswordReset from './PasswordReset'; +import ConfirmationCode from './ConfirmationCode'; +import NewPassword from './NewPassword'; +import ResetSuccessful from './ResetSuccessful'; const Password = () => { - return
Password
; + const [passwordStep, setPasswordStep] = useState(1); + + return ( +
+
+ {passwordStep === 1 && ( + setPasswordStep(2)} /> + )} + {passwordStep === 2 && ( + setPasswordStep(3)} /> + )} + {passwordStep === 3 && ( + setPasswordStep(4)} /> + )} + {passwordStep === 4 && } +
+ + {/* Step Indicator */} +
+ {[1, 2, 3, 4].map((step) => ( +
+ ))} +
+
+ ); }; export default Password; diff --git a/app/(dashboard)/settings/_components/PasswordReset.tsx b/app/(dashboard)/settings/_components/PasswordReset.tsx new file mode 100644 index 0000000..933d8cd --- /dev/null +++ b/app/(dashboard)/settings/_components/PasswordReset.tsx @@ -0,0 +1,59 @@ +import { LockKeyhole } from 'lucide-react'; +import React from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; + +type Props = { + nextPasswordStep: () => void; +}; + +const PasswordReset = ({ nextPasswordStep }: Props) => { + const { register, handleSubmit, watch } = useForm(); + + const handleOnSubmit = (data: FieldValues) => { + nextPasswordStep(); + console.log(data); + }; + + const emailValue = watch('email'); + const passwordValue = watch('password'); + + return ( +
+
+ +
+
+

+ Reset your password +

+

+ Want to reset your password? Please enter your email address and + current password and you'll be sent a 4-digit code. +

+
+
+ + + +
+
+ ); +}; + +export default PasswordReset; diff --git a/app/(dashboard)/settings/_components/ResetSuccessful.tsx b/app/(dashboard)/settings/_components/ResetSuccessful.tsx new file mode 100644 index 0000000..b5ca783 --- /dev/null +++ b/app/(dashboard)/settings/_components/ResetSuccessful.tsx @@ -0,0 +1,33 @@ +import { ShieldCheck } from 'lucide-react'; +import { useRouter } from 'next/navigation'; +import React from 'react'; + +const ResetSuccessful = () => { + const router = useRouter(); + + return ( +
+
+ +
+
+

+ Password reset! +

+

+ Your password has been successfully reset. Click below to log back in. +

+
+ + +
+ ); +}; + +export default ResetSuccessful; From 7517c35aad92d7bc4a644d0dbdb977030aed5da9 Mon Sep 17 00:00:00 2001 From: Ifeoma Date: Wed, 22 Jan 2025 15:04:58 +0100 Subject: [PATCH 5/5] bug fix: disolve unused function --- app/(dashboard)/settings/_components/ConfirmationCode.tsx | 1 - app/(dashboard)/settings/_components/NewPassword.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/app/(dashboard)/settings/_components/ConfirmationCode.tsx b/app/(dashboard)/settings/_components/ConfirmationCode.tsx index e3196ca..d1bbd1c 100644 --- a/app/(dashboard)/settings/_components/ConfirmationCode.tsx +++ b/app/(dashboard)/settings/_components/ConfirmationCode.tsx @@ -1,5 +1,4 @@ import { Columns3 } from 'lucide-react'; -import { useRouter } from 'next/router'; import React, { useRef, useState } from 'react'; import { useForm } from 'react-hook-form'; diff --git a/app/(dashboard)/settings/_components/NewPassword.tsx b/app/(dashboard)/settings/_components/NewPassword.tsx index 9207471..a628bbd 100644 --- a/app/(dashboard)/settings/_components/NewPassword.tsx +++ b/app/(dashboard)/settings/_components/NewPassword.tsx @@ -1,5 +1,4 @@ import { LockKeyhole } from 'lucide-react'; -import { useRouter } from 'next/navigation'; import React from 'react'; import { FieldValues, useForm } from 'react-hook-form';