Skip to content

Commit

Permalink
button v2 added
Browse files Browse the repository at this point in the history
  • Loading branch information
sinanptm committed Sep 19, 2024
1 parent ba8effa commit 92bc352
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 148 deletions.
10 changes: 5 additions & 5 deletions client/app/(patient)/profile/@appointments/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { useGetAppointmentsPatient } from "@/lib/hooks/appointment/useAppointmen
import { useRouter } from "next/navigation";
import { format } from "date-fns";
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import GetStatusBadge from "@/components/doctor/appointment/GetStatusBadge";
import { Calendar, FileText, Video, User } from "lucide-react";
import { useState } from "react";
import { ButtonV2 } from "@/components/common/ButtonV2";

const AppointmentsPageSection = ({ searchParams }: { searchParams: { page: number } }) => {
const page = searchParams.page || 0;
Expand Down Expand Up @@ -60,14 +60,14 @@ const AppointmentsPageSection = ({ searchParams }: { searchParams: { page: numbe
</div>
</CardContent>
<CardFooter className="py-2 px-4 bg-gray-750 border-t border-gray-700 flex justify-end">
<Button
variant="outline"
<ButtonV2
variant="gooeyRight"
size="sm"
onClick={() => handleViewDetails(appointment._id!)}
className="text-green-400 hover:text-green-300 hover:bg-gray-700 border-green-500"
className="text-green-400 border-green-500"
>
View Details
</Button>
</ButtonV2>
</CardFooter>
</Card>
))}
Expand Down
4 changes: 2 additions & 2 deletions client/app/(patient)/profile/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const ProfilePageLayout = ({ children, appointments }: Props) => {
}

return (
<div className="min-h-screen p-4 sm:p-6 md:p-8">
<div className="max-w-4xl mx-auto space-y-4 sm:space-y-6">
<div className="min-h-screen p-1 sm:p-6 md:p-8">
<div className="max-w-4xl mx-auto space-y-1 sm:space-y-6">
<NavSection setSection={setSection} patientData={patientData!} refetch={refetch} />
{section === "profile" && children}
{section === "appointments" && appointments}
Expand Down
8 changes: 4 additions & 4 deletions client/app/(patient)/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -31,15 +31,15 @@ export default function PatientProfilePage() {
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-2xl font-bold text-primary">Personal Information</CardTitle>
<Button
variant="outline"
<ButtonV2
variant="shine"
size="sm"
className="h-8 w-8 p-0"
onClick={() => setIsOpen(!isOpen)}
aria-label="Edit personal information"
>
<Image alt="Edit" src={"/assets/icons/edit.svg"} width={23} height={23} className="h-6 w-6" />
</Button>
</ButtonV2>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2 pt-4">
{infoItems.map((item, index) => (
Expand Down
79 changes: 79 additions & 0 deletions client/components/common/ButtonV2.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}

export type ButtonIconProps = IconProps | IconRefProps

const ButtonV2 = React.forwardRef<HTMLButtonElement, ButtonProps & ButtonIconProps>(
({ className, variant, size, asChild = false, Icon, iconPlacement, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}>
{Icon && iconPlacement === "left" && (
<div className="w-0 translate-x-[0%] pr-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-100 group-hover:pr-2 group-hover:opacity-100">
<Icon />
</div>
)}
<Slottable>{props.children}</Slottable>
{Icon && iconPlacement === "right" && (
<div className="w-0 translate-x-[100%] pl-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-0 group-hover:pl-2 group-hover:opacity-100">
<Icon />
</div>
)}
</Comp>
)
}
)
ButtonV2.displayName = "Button"

export { ButtonV2, buttonVariants }
26 changes: 16 additions & 10 deletions client/components/layout/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -65,26 +66,31 @@ export const NavBar = () => {
}
};

const handleLinkClick = () => {
const handleLinkHome = () => {
setIsSheetOpen(false);
};

const handleLinkClick = (link:string) => {
route.push(link)
setIsSheetOpen(false);
};

return (
<header className="sticky top-0 flex h-16 items-center gap-4 border-b bg-dark-300 bg-opacity-55 px-4 md:px-6 z-50">
<nav className="hidden flex-col gap-6 text-lg font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6">
<Link href="/" className="flex items-center gap-2 text-lg font-semibold md:text-base" prefetch={false}>
<Package2 className="h-6 w-6" onClick={handleLinkClick} />
<Package2 className="h-6 w-6" onClick={handleLinkHome} />
<span className="sr-only">Acme Inc</span>
</Link>
{NavLinks.map((link) => (
<Link
href={link.href}
<ButtonV2
variant={'linkHover2'}
onClick={()=>handleLinkClick(link.href)}
size={'sm'}
key={link.label + link.href}
className="text-muted-foreground transition-colors hover:text-foreground"
prefetch={false}
>
{link.label}
</Link>
</ButtonV2>
))}
</nav>
<Sheet modal open={isSheetOpen} onOpenChange={setIsSheetOpen}>
Expand Down Expand Up @@ -114,7 +120,7 @@ export const NavBar = () => {
<Link
href={link.href}
key={link.label + link.href}
onClick={handleLinkClick}
onClick={handleLinkHome}
className="text-muted-foreground hover:text-foreground"
prefetch={false}
>
Expand Down Expand Up @@ -143,7 +149,7 @@ export const NavBar = () => {
</form>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="rounded-full">
<ButtonV2 variant="ghost" size="icon" className="rounded-full">
<Image
src="/assets/icons/circle-user.svg"
width={30}
Expand All @@ -152,7 +158,7 @@ export const NavBar = () => {
alt="Avatar"
/>
<span className="sr-only">Toggle user menu</span>
</Button>
</ButtonV2>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="mt-3">
{patientToken !== "" ? (
Expand Down
14 changes: 8 additions & 6 deletions client/components/patient/clinicians/DoctorsSection.tsx
Original file line number Diff line number Diff line change
@@ -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"

Expand All @@ -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 <p className="text-center text-lg mb-16">No doctors available at the moment. Please check back later.</p>
Expand All @@ -46,4 +48,4 @@ export default function DoctorPagination({ initialData }: DoctorPaginationProps)
/>
</div>
)
}
}
17 changes: 11 additions & 6 deletions client/components/patient/home/ImageSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<ImagesSlider className="h-[40rem] z-10" images={SliderImages}>
<motion.div
Expand All @@ -25,14 +28,16 @@ const ImageSlider = () => {
Virtual Specialty Care for Everyone.
</motion.p>
<div className="flex flex-col md:flex-row md:space-x-4 space-y-4 md:space-y-0 items-center justify-center">
<button className="px-3 py-1.5 backdrop-blur-sm border bg-emerald-300/10 border-emerald-500/20 text-white text-sm md:text-base rounded-full relative">
<span>Join now →</span>
<div className="absolute inset-x-0 h-px -bottom-px bg-gradient-to-r w-3/4 mx-auto from-transparent via-emerald-500 to-transparent" />
</button>
<button className="px-3 py-1.5 backdrop-blur-sm border bg-emerald-300/10 border-emerald-500/20 text-white text-sm md:text-base rounded-full relative">
{!patientToken && (
<ButtonV2 variant={'gooeyRight'} className="px-3 py-1.5 backdrop-blur-sm border bg-emerald-300/10 border-emerald-500/20 text-white text-sm md:text-base rounded-full relative">
<span>Join now →</span>
<div className="absolute inset-x-0 h-px -bottom-px bg-gradient-to-r w-3/4 mx-auto from-transparent via-emerald-500 to-transparent" />
</ButtonV2>
)}
<ButtonV2 variant={'gooeyRight'} className="px-3 py-1.5 backdrop-blur-sm border bg-emerald-300/10 border-emerald-500/20 text-white text-sm md:text-base rounded-full relative">
<span>Book an Appointment now</span>
<div className="absolute inset-x-0 h-px -bottom-px bg-gradient-to-r w-3/4 mx-auto from-transparent via-emerald-500 to-transparent" />
</button>
</ButtonV2>
</div>
</motion.div>
</ImagesSlider>
Expand Down
16 changes: 8 additions & 8 deletions client/components/patient/profile/NavSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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"
/>
<Button
variant="outline"
<ButtonV2
variant="gooeyLeft"
className="absolute bottom-0 right-0 mb-2 mr-2 p-2 bg-white rounded-full"
onClick={handleUploadClick}
>
<Image src="/assets/icons/upload.svg" alt="Upload" width={24} height={24} />
</Button>
</ButtonV2>
</div>
<div className="text-center sm:text-left">
<h1 className="text-2xl font-bold">{patientData.name}</h1>
Expand All @@ -60,12 +60,12 @@ export default function NavSection({ setSection, patientData, refetch }: Props)
</div>
<CardContent className="p-4 sm:p-6">
<div className="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-4">
<Button variant="outline" onClick={() => handleClick("profile")} className="flex-1">
<ButtonV2 variant="shine" onClick={() => handleClick("profile")} className="flex-1">
Profile
</Button>
<Button variant="outline" onClick={() => handleClick("appointments")} className="flex-1">
</ButtonV2>
<ButtonV2 variant="shine" onClick={() => handleClick("appointments")} className="flex-1">
Appointments
</Button>
</ButtonV2>
</div>
</CardContent>
<UploadProfileModel open={isFileModel} setOpen={setFileModel} patientData={patientData} refetch={refetch} />
Expand Down
Loading

1 comment on commit 92bc352

@vercel
Copy link

@vercel vercel bot commented on 92bc352 Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.