+
{section === "profile" && children}
{section === "appointments" && appointments}
diff --git a/client/app/(patient)/profile/page.tsx b/client/app/(patient)/profile/page.tsx
index 1755b058..48e5f63b 100644
--- a/client/app/(patient)/profile/page.tsx
+++ b/client/app/(patient)/profile/page.tsx
@@ -1,11 +1,11 @@
'use client'
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import Image from "next/image";
import { useState } from "react";
import UpdateProfilePatient from "@/components/models/patient/UpdateProfilePatient";
import { useGetPatientProfile } from "@/lib/hooks/patient/usePatient";
+import { ButtonV2 } from "@/components/common/ButtonV2";
export default function PatientProfilePage() {
const { data: patientData, isLoading, refetch } = useGetPatientProfile();
@@ -31,15 +31,15 @@ export default function PatientProfilePage() {
Personal Information
-
+
{infoItems.map((item, index) => (
diff --git a/client/components/common/ButtonV2.tsx b/client/components/common/ButtonV2.tsx
new file mode 100644
index 00000000..080db6a3
--- /dev/null
+++ b/client/components/common/ButtonV2.tsx
@@ -0,0 +1,79 @@
+import * as React from "react"
+import { Slot, Slottable } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ default: "bg-zinc-800 text-zinc-100 hover:bg-zinc-700",
+ destructive: "bg-red-900 text-red-100 hover:bg-red-800",
+ outline: "border border-zinc-700 bg-transparent hover:bg-zinc-800 hover:text-zinc-100",
+ secondary: "bg-zinc-700 text-zinc-100 hover:bg-zinc-600",
+ ghost: "hover:bg-zinc-800 hover:text-zinc-100",
+ link: "text-zinc-100 underline-offset-4 hover:underline",
+ expandIcon: "group relative text-zinc-100 bg-zinc-800 hover:bg-zinc-700",
+ ringHover: "bg-zinc-800 text-zinc-100 transition-all duration-300 hover:bg-zinc-700 hover:ring-2 hover:ring-zinc-600 hover:ring-offset-2 hover:ring-offset-zinc-900",
+ shine: "text-zinc-100 animate-shine bg-gradient-to-r from-zinc-800 via-zinc-700 to-zinc-800 bg-[length:400%_100%]",
+ gooeyRight: "text-zinc-100 relative bg-zinc-800 z-0 overflow-hidden transition-all duration-500 before:absolute before:inset-0 before:-z-10 before:translate-x-[150%] before:translate-y-[150%] before:scale-[2.5] before:rounded-[100%] before:bg-gradient-to-r from-zinc-700 before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%]",
+ gooeyLeft: "text-zinc-100 relative bg-zinc-800 z-0 overflow-hidden transition-all duration-500 after:absolute after:inset-0 after:-z-10 after:translate-x-[-150%] after:translate-y-[150%] after:scale-[2.5] after:rounded-[100%] after:bg-gradient-to-l from-zinc-700 after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%]",
+ linkHover1: "relative text-zinc-100 after:absolute after:bg-zinc-100 after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-left after:scale-x-100 hover:after:origin-bottom-right hover:after:scale-x-0 after:transition-transform after:ease-in-out after:duration-300",
+ linkHover2: "relative text-zinc-100 after:absolute after:bg-zinc-100 after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-right after:scale-x-0 hover:after:origin-bottom-left hover:after:scale-x-100 after:transition-transform after:ease-in-out after:duration-300",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+interface IconProps {
+ Icon: React.ElementType
+ iconPlacement: "left" | "right"
+}
+
+interface IconRefProps {
+ Icon?: never
+ iconPlacement?: undefined
+}
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+export type ButtonIconProps = IconProps | IconRefProps
+
+const ButtonV2 = React.forwardRef(
+ ({ className, variant, size, asChild = false, Icon, iconPlacement, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+
+ {Icon && iconPlacement === "left" && (
+
+
+
+ )}
+ {props.children}
+ {Icon && iconPlacement === "right" && (
+
+
+
+ )}
+
+ )
+ }
+)
+ButtonV2.displayName = "Button"
+
+export { ButtonV2, buttonVariants }
\ No newline at end of file
diff --git a/client/components/layout/NavBar.tsx b/client/components/layout/NavBar.tsx
index 363b6c11..f7bf9a7c 100644
--- a/client/components/layout/NavBar.tsx
+++ b/client/components/layout/NavBar.tsx
@@ -21,6 +21,7 @@ import { useLogoutMutation } from "@/lib/hooks/patient/usePatientAuth";
import { toast } from "../ui/use-toast";
import { useState } from "react";
import LogoutModel from "../models/LogoutModel";
+import { ButtonV2 } from "../common/ButtonV2";
export const NavBar = () => {
const path = usePathname();
@@ -65,7 +66,12 @@ export const NavBar = () => {
}
};
- const handleLinkClick = () => {
+ const handleLinkHome = () => {
+ setIsSheetOpen(false);
+ };
+
+ const handleLinkClick = (link:string) => {
+ route.push(link)
setIsSheetOpen(false);
};
@@ -73,18 +79,18 @@ export const NavBar = () => {
@@ -114,7 +120,7 @@ export const NavBar = () => {
@@ -143,7 +149,7 @@ export const NavBar = () => {
-
+
{patientToken !== "" ? (
diff --git a/client/components/patient/clinicians/DoctorsSection.tsx b/client/components/patient/clinicians/DoctorsSection.tsx
index 8298b994..dd63d861 100644
--- a/client/components/patient/clinicians/DoctorsSection.tsx
+++ b/client/components/patient/clinicians/DoctorsSection.tsx
@@ -1,7 +1,7 @@
'use client'
import React, { useCallback, useMemo, useState } from "react"
-import { IDoctor, PaginatedResult } from "@/types"
+import { IDoctor } from "@/types"
import { DoctorCard } from "@/components/patient/clinicians/DoctorCard"
import Pagination from "@/components/navigation/Pagination"
@@ -11,19 +11,21 @@ interface DoctorPaginationProps {
export default function DoctorPagination({ initialData }: DoctorPaginationProps) {
const [currentPage, setCurrentPage] = useState(1)
- const [data] = useState(initialData)
+ const [data] = useState(initialData)
const pageSize = 2
const totalPages = useMemo(() => Math.ceil(initialData.length / pageSize), [initialData.length, pageSize])
- const paginatedItems = useMemo(() =>
+ const paginatedItems = useMemo(() =>
initialData.slice((currentPage - 1) * pageSize, currentPage * pageSize),
[initialData, currentPage, pageSize]
)
const handlePageChange = useCallback((newPage: number) => {
- setCurrentPage(newPage)
- }, [])
+ if (newPage > 0 && newPage <= totalPages) {
+ setCurrentPage(newPage)
+ }
+ }, [totalPages])
if (initialData.length === 0) {
return No doctors available at the moment. Please check back later.
@@ -46,4 +48,4 @@ export default function DoctorPagination({ initialData }: DoctorPaginationProps)
/>
)
-}
\ No newline at end of file
+}
diff --git a/client/components/patient/home/ImageSlider.tsx b/client/components/patient/home/ImageSlider.tsx
index 5bcee13a..df7723b2 100644
--- a/client/components/patient/home/ImageSlider.tsx
+++ b/client/components/patient/home/ImageSlider.tsx
@@ -3,8 +3,11 @@ import { motion } from "framer-motion";
import React from "react";
import { ImagesSlider } from "@/components/ui/images-slider";
import { SliderImages } from "@/constants";
+import { useAuth } from "@/lib/hooks/useAuth";
+import { ButtonV2 } from "@/components/common/ButtonV2";
const ImageSlider = () => {
+ const { patientToken } = useAuth()
return (
{
Virtual Specialty Care for Everyone.
-
-
+
diff --git a/client/components/patient/profile/NavSection.tsx b/client/components/patient/profile/NavSection.tsx
index 11ba1537..333bd931 100644
--- a/client/components/patient/profile/NavSection.tsx
+++ b/client/components/patient/profile/NavSection.tsx
@@ -3,9 +3,9 @@
import { useState } from "react";
import Image from "next/image";
import { Card, CardContent } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
import { IPatient } from "@/types";
import UploadProfileModel from "@/components/models/patient/UploadProfileModel";
+import { ButtonV2 } from "@/components/common/ButtonV2";
interface Props {
setSection: (state: "profile" | "appointments" ) => void;
@@ -44,13 +44,13 @@ export default function NavSection({ setSection, patientData, refetch }: Props)
height={100}
className="rounded-full border-4 border-white h-32 w-32"
/>
-
+
diff --git a/client/components/skeletons/ProfilePage.tsx b/client/components/skeletons/ProfilePage.tsx
index acff3d87..bd5ad2f7 100644
--- a/client/components/skeletons/ProfilePage.tsx
+++ b/client/components/skeletons/ProfilePage.tsx
@@ -29,45 +29,17 @@ export default function ProfileSkeleton() {
{/* Profile Section Skeleton */}
-