87 | >(({ className, ...props }, ref) => (
88 | [role=checkbox]]:translate-y-[2px]",
92 | className
93 | )}
94 | {...props}
95 | />
96 | ))
97 | TableCell.displayName = "TableCell"
98 |
99 | const TableCaption = React.forwardRef<
100 | HTMLTableCaptionElement,
101 | React.HTMLAttributes
102 | >(({ className, ...props }, ref) => (
103 |
108 | ))
109 | TableCaption.displayName = "TableCaption"
110 |
111 | export {
112 | Table,
113 | TableHeader,
114 | TableBody,
115 | TableFooter,
116 | TableHead,
117 | TableRow,
118 | TableCell,
119 | TableCaption,
120 | }
121 |
--------------------------------------------------------------------------------
/components/ui/drawer.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import { Drawer as DrawerPrimitive } from "vaul";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Drawer = ({
9 | shouldScaleBackground = false,
10 | ...props
11 | }: React.ComponentProps) => (
12 |
16 | );
17 | Drawer.displayName = "Drawer";
18 |
19 | const DrawerTrigger = DrawerPrimitive.Trigger;
20 |
21 | const DrawerPortal = DrawerPrimitive.Portal;
22 |
23 | const DrawerClose = DrawerPrimitive.Close;
24 |
25 | const DrawerOverlay = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
34 | ));
35 | DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
36 |
37 | const DrawerContent = React.forwardRef<
38 | React.ElementRef,
39 | React.ComponentPropsWithoutRef
40 | >(({ className, children, ...props }, ref) => (
41 |
42 |
43 |
51 |
52 | {children}
53 |
54 |
55 | ));
56 | DrawerContent.displayName = "DrawerContent";
57 |
58 | const DrawerHeader = ({
59 | className,
60 | ...props
61 | }: React.HTMLAttributes) => (
62 |
66 | );
67 | DrawerHeader.displayName = "DrawerHeader";
68 |
69 | const DrawerFooter = ({
70 | className,
71 | ...props
72 | }: React.HTMLAttributes) => (
73 |
77 | );
78 | DrawerFooter.displayName = "DrawerFooter";
79 |
80 | const DrawerTitle = React.forwardRef<
81 | React.ElementRef,
82 | React.ComponentPropsWithoutRef
83 | >(({ className, ...props }, ref) => (
84 |
92 | ));
93 | DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
94 |
95 | const DrawerDescription = React.forwardRef<
96 | React.ElementRef,
97 | React.ComponentPropsWithoutRef
98 | >(({ className, ...props }, ref) => (
99 |
104 | ));
105 | DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
106 |
107 | export {
108 | Drawer,
109 | DrawerPortal,
110 | DrawerOverlay,
111 | DrawerTrigger,
112 | DrawerClose,
113 | DrawerContent,
114 | DrawerHeader,
115 | DrawerFooter,
116 | DrawerTitle,
117 | DrawerDescription,
118 | };
119 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/drawer.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import { Drawer as DrawerPrimitive } from "vaul";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Drawer = ({
9 | shouldScaleBackground = false,
10 | ...props
11 | }: React.ComponentProps) => (
12 |
16 | );
17 | Drawer.displayName = "Drawer";
18 |
19 | const DrawerTrigger = DrawerPrimitive.Trigger;
20 |
21 | const DrawerPortal = DrawerPrimitive.Portal;
22 |
23 | const DrawerClose = DrawerPrimitive.Close;
24 |
25 | const DrawerOverlay = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
34 | ));
35 | DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
36 |
37 | const DrawerContent = React.forwardRef<
38 | React.ElementRef,
39 | React.ComponentPropsWithoutRef
40 | >(({ className, children, ...props }, ref) => (
41 |
42 |
43 |
51 |
52 | {children}
53 |
54 |
55 | ));
56 | DrawerContent.displayName = "DrawerContent";
57 |
58 | const DrawerHeader = ({
59 | className,
60 | ...props
61 | }: React.HTMLAttributes) => (
62 |
66 | );
67 | DrawerHeader.displayName = "DrawerHeader";
68 |
69 | const DrawerFooter = ({
70 | className,
71 | ...props
72 | }: React.HTMLAttributes) => (
73 |
77 | );
78 | DrawerFooter.displayName = "DrawerFooter";
79 |
80 | const DrawerTitle = React.forwardRef<
81 | React.ElementRef,
82 | React.ComponentPropsWithoutRef
83 | >(({ className, ...props }, ref) => (
84 |
92 | ));
93 | DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
94 |
95 | const DrawerDescription = React.forwardRef<
96 | React.ElementRef,
97 | React.ComponentPropsWithoutRef
98 | >(({ className, ...props }, ref) => (
99 |
104 | ));
105 | DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
106 |
107 | export {
108 | Drawer,
109 | DrawerPortal,
110 | DrawerOverlay,
111 | DrawerTrigger,
112 | DrawerClose,
113 | DrawerContent,
114 | DrawerHeader,
115 | DrawerFooter,
116 | DrawerTitle,
117 | DrawerDescription,
118 | };
119 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/event-components/listallevents.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import {
3 | Credenza,
4 | CredenzaBody,
5 | CredenzaContent,
6 | CredenzaDescription,
7 | CredenzaHeader,
8 | CredenzaTitle,
9 | CredenzaTrigger
10 | } from "@components/ui/credenza";
11 | import { Button } from "@components/ui/button";
12 | import AddEvent from "@shadcn-fullcalender/calender-components/add-event";
13 | import { CalendarAdd } from "iconsax-react";
14 | import EventModal from "./eventmodal"; // Importing EventModalProps type
15 | import { Eventyearviewbtn } from "./yearviewlist";
16 |
17 | type Event = {
18 | eventname: string;
19 | description: string;
20 | };
21 |
22 | type ButtonProps = {
23 | view: "day" | "year"; // Specify the views available, e.g., "day" or "month"
24 | eventsForDay: Event[]; // Array of Event objects
25 | eventsForDate?: Event[]; // Optional prop for year view (pass if needed)
26 | date?: Date; // Optional prop for the date (pass if needed)
27 | isToday?: boolean; // Optional boolean for checking if the date is today
28 | isCurrentMonth?: boolean; // Optional boolean for checking if the date is in the current month
29 | index?: number; // Optional index prop (if needed for the year view button)
30 | };
31 |
32 | function ListAllEvents({ eventsForDay, view, eventsForDate, date, isToday, isCurrentMonth, index }: ButtonProps) {
33 | return (
34 |
35 |
36 | {view === "day" ? (
37 |
41 | +{eventsForDay.length - 1} more
42 |
43 | ) : (
44 |
52 | )}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | All the events for the day
61 |
62 |
63 |
64 | Click on an event to view more details.
65 |
66 |
67 |
68 | {/* Make the ListAllEvents body scrollable */}
69 |
70 | {
71 | eventsForDay.map((event, index) => (
72 |
73 | ))
74 | }
75 |
78 |
79 |
80 |
81 | );
82 | }
83 |
84 | export default ListAllEvents;
85 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/calender-components/tabs.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { ColumnsIcon, DashboardIcon, GridIcon } from "@radix-ui/react-icons";
3 | type TabTypes = "month" | "year"; // Add more tab types if necessary
4 |
5 | export function Tabs(props: any) {
6 | return (
7 |
8 |
9 | {/* Tab: Week */}
10 | props.setActiveTab("week")}
12 | className={`relative inline-flex gap-3 h-full items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 rounded-md px-2 w-full transition-all duration-500 ease-in-out ${
13 | props.activeTab === ("week" as TabTypes)
14 | ? "bg-secondary text-secondary-foreground"
15 | : "hover:bg-secondary/50 hover:text-secondary-foreground"
16 | } cursor-pointer`}
17 | >
18 |
19 |
26 | Week
27 |
28 |
29 |
30 | {/* Tab: Month */}
31 | props.setActiveTab("month")}
33 | className={`relative inline-flex gap-3 h-full items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 rounded-md px-2 w-full transition-all duration-500 ease-in-out ${
34 | props.activeTab === ("month" as TabTypes)
35 | ? "bg-secondary text-secondary-foreground"
36 | : "hover:bg-secondary/50 hover:text-secondary-foreground"
37 | } cursor-pointer`}
38 | >
39 |
40 |
47 | Month
48 |
49 |
50 |
51 | {/* Tab: Year */}
52 | props.setActiveTab("year")}
54 | className={`relative inline-flex h-full gap-3 items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 rounded-md px-2 w-full transition-all duration-500 ease-in-out ${
55 | props.activeTab === "year"
56 | ? "bg-secondary text-secondary-foreground"
57 | : "hover:bg-secondary/50 hover:text-secondary-foreground"
58 | } cursor-pointer`}
59 | >
60 |
61 |
62 |
69 | Year
70 |
71 |
72 |
73 |
74 | );
75 | }
76 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/calender-components/add-event.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { AddCircle, CalendarAdd } from "iconsax-react";
4 | import EventForm from "./eventform";
5 | import { Credenza, CredenzaBody, CredenzaContent, CredenzaDescription, CredenzaHeader, CredenzaTitle, CredenzaTrigger } from "@shadcn-fullcalender/ui/credenza";
6 | import { Button } from "@shadcn-fullcalender/ui/button";
7 |
8 | type ButtonProps = {
9 | variant?: "default" | "secondary" | "primary"; // Optional variant type
10 | currentDate?: Date; // Optional day prop
11 | buttonText?: string; // Custom text for the button
12 | formTitle?: string; // Custom title for the form
13 | formDescription?: string; // Custom description for the form
14 | icon?: React.ReactNode; // Custom icon for the button
15 | CustomForm?: React.FC<{ currentDate?: Date }>; // Custom form component
16 | };
17 |
18 | function AddEvent({
19 | variant = "default",
20 | currentDate,
21 | buttonText = "Add Event",
22 | formTitle = "Add Event",
23 | formDescription = "Create a new event in your calendar.",
24 | icon = , // Default icon
25 | CustomForm, // Accept custom form component
26 | }: ButtonProps) {
27 |
28 |
29 | return (
30 |
31 |
32 | {variant === "default" ? (
33 |
34 |
35 | {buttonText}
36 |
37 | ) : variant === "secondary" ? (
38 |
42 | {icon}
43 | {buttonText}
44 |
45 | ) : (
46 |
50 | {icon}
51 | {buttonText}
52 |
53 | )}
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | {formTitle}
62 |
63 |
64 |
65 | {formDescription}
66 |
67 |
68 |
69 | {/* Make the modal body scrollable */}
70 |
71 | {CustomForm ? (
72 | // Render custom form if provided
73 | ) : (
74 | // Default form
75 | )}
76 |
77 |
78 |
79 | );
80 | }
81 |
82 | export default AddEvent;
83 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | /* Box sizing rules */
6 | *,
7 | *::before,
8 | *::after {
9 | box-sizing: border-box;
10 | }
11 |
12 | /* Prevent font size inflation */
13 | html {
14 | -moz-text-size-adjust: none;
15 | -webkit-text-size-adjust: none;
16 | text-size-adjust: none;
17 | }
18 |
19 | /* Remove default margin in favour of better control in authored CSS */
20 | body,
21 | h1,
22 | h2,
23 | h3,
24 | h4,
25 | p,
26 | figure,
27 | blockquote,
28 | dl,
29 | dd {
30 | margin-block-end: 0;
31 | }
32 |
33 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
34 | ul[role="list"],
35 | ol[role="list"] {
36 | list-style: none;
37 | }
38 |
39 | /* Set core body defaults */
40 | body {
41 | min-height: 100vh;
42 | line-height: 1.5;
43 | }
44 |
45 | /* Set shorter line heights on headings and interactive elements */
46 | h1,
47 | h2,
48 | h3,
49 | h4,
50 | button,
51 | input,
52 | label {
53 | line-height: 1.1;
54 | }
55 |
56 | /* Balance text wrapping on headings */
57 | h1,
58 | h2,
59 | h3,
60 | h4 {
61 | text-wrap: balance;
62 | }
63 |
64 | /* A elements that don't have a class get default styles */
65 | a:not([class]) {
66 | text-decoration-skip-ink: auto;
67 | color: currentColor;
68 | }
69 |
70 | /* Make images easier to work with */
71 | img,
72 | picture {
73 | max-width: 100%;
74 | display: block;
75 | }
76 |
77 | /* Inherit fonts for inputs and buttons */
78 | input,
79 | button,
80 | textarea,
81 | select {
82 | font-family: inherit;
83 | font-size: inherit;
84 | }
85 |
86 | /* Make sure textareas without a rows attribute are not tiny */
87 | textarea:not([rows]) {
88 | min-height: 10em;
89 | }
90 |
91 | /* Anything that has been anchored to should have extra scroll margin */
92 | :target {
93 | scroll-margin-block: 5ex;
94 | }
95 |
96 | @layer base {
97 | :root {
98 | --background: 0 0% 100%;
99 | --foreground: 0 0% 3.9%;
100 | --card: 0 0% 100%;
101 | --card-foreground: 0 0% 3.9%;
102 | --popover: 0 0% 100%;
103 | --popover-foreground: 0 0% 3.9%;
104 | --primary: 0 0% 9%;
105 | --primary-foreground: 0 0% 98%;
106 | --secondary: 0 0% 96.1%;
107 | --secondary-foreground: 0 0% 9%;
108 | --muted: 0 0% 96.1%;
109 | --muted-foreground: 0 0% 45.1%;
110 | --accent: 0 0% 96.1%;
111 | --accent-foreground: 0 0% 9%;
112 | --destructive: 0 84.2% 60.2%;
113 | --destructive-foreground: 0 0% 98%;
114 | --border: 0 0% 89.8%;
115 | --input: 0 0% 89.8%;
116 | --ring: 0 0% 3.9%;
117 | --chart-1: 12 76% 61%;
118 | --chart-2: 173 58% 39%;
119 | --chart-3: 197 37% 24%;
120 | --chart-4: 43 74% 66%;
121 | --chart-5: 27 87% 67%;
122 | --radius: 0.5rem;
123 | }
124 | .dark {
125 | --background: 0 0% 3.9%;
126 | --foreground: 0 0% 98%;
127 | --card: 0 0% 3.9%;
128 | --card-foreground: 0 0% 98%;
129 | --popover: 0 0% 3.9%;
130 | --popover-foreground: 0 0% 98%;
131 | --primary: 0 0% 98%;
132 | --primary-foreground: 0 0% 9%;
133 | --secondary: 0 0% 14.9%;
134 | --secondary-foreground: 0 0% 98%;
135 | --muted: 0 0% 14.9%;
136 | --muted-foreground: 0 0% 63.9%;
137 | --accent: 0 0% 14.9%;
138 | --accent-foreground: 0 0% 98%;
139 | --destructive: 0 62.8% 30.6%;
140 | --destructive-foreground: 0 0% 98%;
141 | --border: 0 0% 14.9%;
142 | --input: 0 0% 14.9%;
143 | --ring: 0 0% 83.1%;
144 | --chart-1: 220 70% 50%;
145 | --chart-2: 160 60% 45%;
146 | --chart-3: 30 80% 55%;
147 | --chart-4: 280 65% 60%;
148 | --chart-5: 340 75% 55%;
149 | }
150 | }
151 | @layer base {
152 | * {
153 | @apply border-border;
154 | }
155 | body {
156 | @apply bg-background text-foreground;
157 | }
158 | }
159 |
160 | /* Hide Calendar Scrollbar - Week View */
161 | [data-radix-scroll-area-viewport] {
162 | scrollbar-width: none;
163 | -ms-overflow-style: none;
164 | -webkit-overflow-scrolling: touch;
165 | }
166 |
167 | [data-radix-scroll-area-viewport]::-webkit-scrollbar {
168 | display: none
169 | }
--------------------------------------------------------------------------------
/components/ui/credenza.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 |
5 | import { cn } from "@/lib/utils";
6 | import { useMediaQuery } from "@/hooks/use-media-query";
7 | import {
8 | Dialog,
9 | DialogClose,
10 | DialogContent,
11 | DialogDescription,
12 | DialogFooter,
13 | DialogHeader,
14 | DialogTitle,
15 | DialogTrigger,
16 | } from "@/components/ui/dialog";
17 | import {
18 | Drawer,
19 | DrawerClose,
20 | DrawerContent,
21 | DrawerDescription,
22 | DrawerFooter,
23 | DrawerHeader,
24 | DrawerTitle,
25 | DrawerTrigger,
26 | } from "@/components/ui/drawer";
27 |
28 | interface BaseProps {
29 | children: React.ReactNode;
30 | }
31 |
32 | interface RootCredenzaProps extends BaseProps {
33 | open?: boolean;
34 | onOpenChange?: (open: boolean) => void;
35 | }
36 |
37 | interface CredenzaProps extends BaseProps {
38 | className?: string;
39 | asChild?: true;
40 | }
41 |
42 | const desktop = "(min-width: 768px)";
43 |
44 | const Credenza = ({ children, ...props }: RootCredenzaProps) => {
45 | const isDesktop = useMediaQuery(desktop);
46 | const Credenza = isDesktop ? Dialog : Drawer;
47 |
48 | return {children} ;
49 | };
50 |
51 | const CredenzaTrigger = ({ className, children, ...props }: CredenzaProps) => {
52 | const isDesktop = useMediaQuery(desktop);
53 | const CredenzaTrigger = isDesktop ? DialogTrigger : DrawerTrigger;
54 |
55 | return (
56 |
57 | {children}
58 |
59 | );
60 | };
61 |
62 | const CredenzaClose = ({ className, children, ...props }: CredenzaProps) => {
63 | const isDesktop = useMediaQuery(desktop);
64 | const CredenzaClose = isDesktop ? DialogClose : DrawerClose;
65 |
66 | return (
67 |
68 | {children}
69 |
70 | );
71 | };
72 |
73 | const CredenzaContent = ({ className, children, ...props }: CredenzaProps) => {
74 | const isDesktop = useMediaQuery(desktop);
75 | const CredenzaContent = isDesktop ? DialogContent : DrawerContent;
76 |
77 | return (
78 |
79 | {children}
80 |
81 | );
82 | };
83 |
84 | const CredenzaDescription = ({
85 | className,
86 | children,
87 | ...props
88 | }: CredenzaProps) => {
89 | const isDesktop = useMediaQuery(desktop);
90 | const CredenzaDescription = isDesktop ? DialogDescription : DrawerDescription;
91 |
92 | return (
93 |
94 | {children}
95 |
96 | );
97 | };
98 |
99 | const CredenzaHeader = ({ className, children, ...props }: CredenzaProps) => {
100 | const isDesktop = useMediaQuery(desktop);
101 | const CredenzaHeader = isDesktop ? DialogHeader : DrawerHeader;
102 |
103 | return (
104 |
105 | {children}
106 |
107 | );
108 | };
109 |
110 | const CredenzaTitle = ({ className, children, ...props }: CredenzaProps) => {
111 | const isDesktop = useMediaQuery(desktop);
112 | const CredenzaTitle = isDesktop ? DialogTitle : DrawerTitle;
113 |
114 | return (
115 |
116 | {children}
117 |
118 | );
119 | };
120 |
121 | const CredenzaBody = ({ className, children, ...props }: CredenzaProps) => {
122 | return (
123 |
124 | {children}
125 |
126 | );
127 | };
128 |
129 | const CredenzaFooter = ({ className, children, ...props }: CredenzaProps) => {
130 | const isDesktop = useMediaQuery(desktop);
131 | const CredenzaFooter = isDesktop ? DialogFooter : DrawerFooter;
132 |
133 | return (
134 |
135 | {children}
136 |
137 | );
138 | };
139 |
140 | export {
141 | Credenza,
142 | CredenzaTrigger,
143 | CredenzaClose,
144 | CredenzaContent,
145 | CredenzaDescription,
146 | CredenzaHeader,
147 | CredenzaTitle,
148 | CredenzaBody,
149 | CredenzaFooter,
150 | };
151 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/credenza.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 |
5 | import { cn } from "@/lib/utils";
6 | import { useMediaQuery } from "@/hooks/use-media-query";
7 | import {
8 | Dialog,
9 | DialogClose,
10 | DialogContent,
11 | DialogDescription,
12 | DialogFooter,
13 | DialogHeader,
14 | DialogTitle,
15 | DialogTrigger,
16 | } from "@shadcn-fullcalender/ui/dialog";
17 | import {
18 | Drawer,
19 | DrawerClose,
20 | DrawerContent,
21 | DrawerDescription,
22 | DrawerFooter,
23 | DrawerHeader,
24 | DrawerTitle,
25 | DrawerTrigger,
26 | } from "@shadcn-fullcalender/ui/drawer";
27 |
28 | interface BaseProps {
29 | children: React.ReactNode;
30 | }
31 |
32 | interface RootCredenzaProps extends BaseProps {
33 | open?: boolean;
34 | onOpenChange?: (open: boolean) => void;
35 | }
36 |
37 | interface CredenzaProps extends BaseProps {
38 | className?: string;
39 | asChild?: true;
40 | }
41 |
42 | const desktop = "(min-width: 768px)";
43 |
44 | const Credenza = ({ children, ...props }: RootCredenzaProps) => {
45 | const isDesktop = useMediaQuery(desktop);
46 | const Credenza = isDesktop ? Dialog : Drawer;
47 |
48 | return {children} ;
49 | };
50 |
51 | const CredenzaTrigger = ({ className, children, ...props }: CredenzaProps) => {
52 | const isDesktop = useMediaQuery(desktop);
53 | const CredenzaTrigger = isDesktop ? DialogTrigger : DrawerTrigger;
54 |
55 | return (
56 |
57 | {children}
58 |
59 | );
60 | };
61 |
62 | const CredenzaClose = ({ className, children, ...props }: CredenzaProps) => {
63 | const isDesktop = useMediaQuery(desktop);
64 | const CredenzaClose = isDesktop ? DialogClose : DrawerClose;
65 |
66 | return (
67 |
68 | {children}
69 |
70 | );
71 | };
72 |
73 | const CredenzaContent = ({ className, children, ...props }: CredenzaProps) => {
74 | const isDesktop = useMediaQuery(desktop);
75 | const CredenzaContent = isDesktop ? DialogContent : DrawerContent;
76 |
77 | return (
78 |
79 | {children}
80 |
81 | );
82 | };
83 |
84 | const CredenzaDescription = ({
85 | className,
86 | children,
87 | ...props
88 | }: CredenzaProps) => {
89 | const isDesktop = useMediaQuery(desktop);
90 | const CredenzaDescription = isDesktop ? DialogDescription : DrawerDescription;
91 |
92 | return (
93 |
94 | {children}
95 |
96 | );
97 | };
98 |
99 | const CredenzaHeader = ({ className, children, ...props }: CredenzaProps) => {
100 | const isDesktop = useMediaQuery(desktop);
101 | const CredenzaHeader = isDesktop ? DialogHeader : DrawerHeader;
102 |
103 | return (
104 |
105 | {children}
106 |
107 | );
108 | };
109 |
110 | const CredenzaTitle = ({ className, children, ...props }: CredenzaProps) => {
111 | const isDesktop = useMediaQuery(desktop);
112 | const CredenzaTitle = isDesktop ? DialogTitle : DrawerTitle;
113 |
114 | return (
115 |
116 | {children}
117 |
118 | );
119 | };
120 |
121 | const CredenzaBody = ({ className, children, ...props }: CredenzaProps) => {
122 | return (
123 |
124 | {children}
125 |
126 | );
127 | };
128 |
129 | const CredenzaFooter = ({ className, children, ...props }: CredenzaProps) => {
130 | const isDesktop = useMediaQuery(desktop);
131 | const CredenzaFooter = isDesktop ? DialogFooter : DrawerFooter;
132 |
133 | return (
134 |
135 | {children}
136 |
137 | );
138 | };
139 |
140 | export {
141 | Credenza,
142 | CredenzaTrigger,
143 | CredenzaClose,
144 | CredenzaContent,
145 | CredenzaDescription,
146 | CredenzaHeader,
147 | CredenzaTitle,
148 | CredenzaBody,
149 | CredenzaFooter,
150 | };
151 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/utils/day-render.tsx:
--------------------------------------------------------------------------------
1 | import { addDays, format, parseISO } from "date-fns";
2 |
3 | import React from "react";
4 | import { Event } from "@shadcn-fullcalender/types/event";
5 | import EventModal from "@shadcn-fullcalender/event-components/eventmodal";
6 | import AddEvent from "@shadcn-fullcalender/calender-components/add-event";
7 | import ListAllEvents from "@shadcn-fullcalender/event-components/listallevents";
8 |
9 | interface RenderDaysInMonthProps {
10 | currentDate: Date;
11 | events: Event[];
12 | startWeek: Date;
13 | daysOfWeek: string[];
14 | }
15 |
16 | export const renderDaysInMonth = ({
17 | currentDate,
18 | events,
19 | startWeek,
20 | }: RenderDaysInMonthProps) => {
21 | const days: React.ReactNode[] = [];
22 | let day = startWeek;
23 |
24 | // Today's date
25 | const todayDate = format(new Date(), "d");
26 | const todayMonth = format(new Date(), "M");
27 | const todayYear = format(new Date(), "yyyy");
28 |
29 | for (let i = 0; i < 6; i++) {
30 | for (let j = 0; j < 7; j++) {
31 | if (format(day, "M") === format(currentDate, "M")) {
32 | const isToday =
33 | format(day, "d") === todayDate &&
34 | format(day, "M") === todayMonth &&
35 | format(day, "yyyy") === todayYear;
36 |
37 | // Filter events for the specific day
38 | const eventsForDay = events.filter((event) => {
39 | const startDate = format(parseISO(event.startdate), "yyyy-MM-dd");
40 | const endDate = format(parseISO(event.enddate), "yyyy-MM-dd");
41 | const formattedDay = format(day, "yyyy-MM-dd");
42 |
43 | if (startDate === endDate) {
44 | return startDate === formattedDay;
45 | } else {
46 | return formattedDay >= startDate && formattedDay <= endDate;
47 | }
48 | });
49 |
50 | days.push(
51 |
56 | {/* Day number */}
57 |
63 | {format(day, "d")}
64 |
65 |
66 | {/* Events list */}
67 |
68 | {eventsForDay.length === 0 &&
}
69 | {eventsForDay.length === 1 && (
70 | <>
71 |
72 |
73 | >
74 | )}
75 | {eventsForDay.length > 1 && (
76 | <>
77 |
80 | {eventsForDay.length > 1 && (
81 |
86 | )}
87 | >
88 | )}
89 |
90 |
91 | );
92 | }
93 | day = addDays(day, 1);
94 | }
95 | }
96 | return days;
97 | };
98 |
--------------------------------------------------------------------------------
/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as DialogPrimitive from "@radix-ui/react-dialog";
5 | import { Cross2Icon } from "@radix-ui/react-icons";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const Dialog = DialogPrimitive.Root;
10 |
11 | const DialogTrigger = DialogPrimitive.Trigger;
12 |
13 | const DialogPortal = DialogPrimitive.Portal;
14 |
15 | const DialogClose = DialogPrimitive.Close;
16 |
17 | const DialogOverlay = React.forwardRef<
18 | React.ElementRef,
19 | React.ComponentPropsWithoutRef
20 | >(({ className, ...props }, ref) => (
21 |
29 | ));
30 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
31 |
32 | const DialogContent = React.forwardRef<
33 | React.ElementRef,
34 | React.ComponentPropsWithoutRef
35 | >(({ className, children, ...props }, ref) => (
36 |
37 |
38 |
46 | {children}
47 |
48 |
49 | Close
50 |
51 |
52 |
53 | ));
54 | DialogContent.displayName = DialogPrimitive.Content.displayName;
55 |
56 | const DialogHeader = ({
57 | className,
58 | ...props
59 | }: React.HTMLAttributes) => (
60 |
67 | );
68 | DialogHeader.displayName = "DialogHeader";
69 |
70 | const DialogFooter = ({
71 | className,
72 | ...props
73 | }: React.HTMLAttributes) => (
74 |
81 | );
82 | DialogFooter.displayName = "DialogFooter";
83 |
84 | const DialogTitle = React.forwardRef<
85 | React.ElementRef,
86 | React.ComponentPropsWithoutRef
87 | >(({ className, ...props }, ref) => (
88 |
96 | ));
97 | DialogTitle.displayName = DialogPrimitive.Title.displayName;
98 |
99 | const DialogDescription = React.forwardRef<
100 | React.ElementRef,
101 | React.ComponentPropsWithoutRef
102 | >(({ className, ...props }, ref) => (
103 |
108 | ));
109 | DialogDescription.displayName = DialogPrimitive.Description.displayName;
110 |
111 | export {
112 | Dialog,
113 | DialogPortal,
114 | DialogOverlay,
115 | DialogTrigger,
116 | DialogClose,
117 | DialogContent,
118 | DialogHeader,
119 | DialogFooter,
120 | DialogTitle,
121 | DialogDescription,
122 | };
123 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as DialogPrimitive from "@radix-ui/react-dialog";
5 | import { Cross2Icon } from "@radix-ui/react-icons";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const Dialog = DialogPrimitive.Root;
10 |
11 | const DialogTrigger = DialogPrimitive.Trigger;
12 |
13 | const DialogPortal = DialogPrimitive.Portal;
14 |
15 | const DialogClose = DialogPrimitive.Close;
16 |
17 | const DialogOverlay = React.forwardRef<
18 | React.ElementRef,
19 | React.ComponentPropsWithoutRef
20 | >(({ className, ...props }, ref) => (
21 |
29 | ));
30 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
31 |
32 | const DialogContent = React.forwardRef<
33 | React.ElementRef,
34 | React.ComponentPropsWithoutRef
35 | >(({ className, children, ...props }, ref) => (
36 |
37 |
38 |
46 | {children}
47 |
48 |
49 | Close
50 |
51 |
52 |
53 | ));
54 | DialogContent.displayName = DialogPrimitive.Content.displayName;
55 |
56 | const DialogHeader = ({
57 | className,
58 | ...props
59 | }: React.HTMLAttributes) => (
60 |
67 | );
68 | DialogHeader.displayName = "DialogHeader";
69 |
70 | const DialogFooter = ({
71 | className,
72 | ...props
73 | }: React.HTMLAttributes) => (
74 |
81 | );
82 | DialogFooter.displayName = "DialogFooter";
83 |
84 | const DialogTitle = React.forwardRef<
85 | React.ElementRef,
86 | React.ComponentPropsWithoutRef
87 | >(({ className, ...props }, ref) => (
88 |
96 | ));
97 | DialogTitle.displayName = DialogPrimitive.Title.displayName;
98 |
99 | const DialogDescription = React.forwardRef<
100 | React.ElementRef,
101 | React.ComponentPropsWithoutRef
102 | >(({ className, ...props }, ref) => (
103 |
108 | ));
109 | DialogDescription.displayName = DialogPrimitive.Description.displayName;
110 |
111 | export {
112 | Dialog,
113 | DialogPortal,
114 | DialogOverlay,
115 | DialogTrigger,
116 | DialogClose,
117 | DialogContent,
118 | DialogHeader,
119 | DialogFooter,
120 | DialogTitle,
121 | DialogDescription,
122 | };
123 |
--------------------------------------------------------------------------------
/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SheetPrimitive from "@radix-ui/react-dialog"
5 | import { Cross2Icon } from "@radix-ui/react-icons"
6 | import { cva, type VariantProps } from "class-variance-authority"
7 |
8 | import { cn } from "@/lib/utils"
9 |
10 | const Sheet = SheetPrimitive.Root
11 |
12 | const SheetTrigger = SheetPrimitive.Trigger
13 |
14 | const SheetClose = SheetPrimitive.Close
15 |
16 | const SheetPortal = SheetPrimitive.Portal
17 |
18 | const SheetOverlay = React.forwardRef<
19 | React.ElementRef,
20 | React.ComponentPropsWithoutRef
21 | >(({ className, ...props }, ref) => (
22 |
30 | ))
31 | SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
32 |
33 | const sheetVariants = cva(
34 | "fixed z-50 gap-4 bg-background p-6 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",
35 | {
36 | variants: {
37 | side: {
38 | top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
39 | bottom:
40 | "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
41 | 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",
42 | right:
43 | "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
44 | },
45 | },
46 | defaultVariants: {
47 | side: "right",
48 | },
49 | }
50 | )
51 |
52 | interface SheetContentProps
53 | extends React.ComponentPropsWithoutRef,
54 | VariantProps {}
55 |
56 | const SheetContent = React.forwardRef<
57 | React.ElementRef,
58 | SheetContentProps
59 | >(({ side = "right", className, children, ...props }, ref) => (
60 |
61 |
62 |
67 |
68 |
69 | Close
70 |
71 | {children}
72 |
73 |
74 | ))
75 | SheetContent.displayName = SheetPrimitive.Content.displayName
76 |
77 | const SheetHeader = ({
78 | className,
79 | ...props
80 | }: React.HTMLAttributes) => (
81 |
88 | )
89 | SheetHeader.displayName = "SheetHeader"
90 |
91 | const SheetFooter = ({
92 | className,
93 | ...props
94 | }: React.HTMLAttributes) => (
95 |
102 | )
103 | SheetFooter.displayName = "SheetFooter"
104 |
105 | const SheetTitle = React.forwardRef<
106 | React.ElementRef,
107 | React.ComponentPropsWithoutRef
108 | >(({ className, ...props }, ref) => (
109 |
114 | ))
115 | SheetTitle.displayName = SheetPrimitive.Title.displayName
116 |
117 | const SheetDescription = React.forwardRef<
118 | React.ElementRef,
119 | React.ComponentPropsWithoutRef
120 | >(({ className, ...props }, ref) => (
121 |
126 | ))
127 | SheetDescription.displayName = SheetPrimitive.Description.displayName
128 |
129 | export {
130 | Sheet,
131 | SheetPortal,
132 | SheetOverlay,
133 | SheetTrigger,
134 | SheetClose,
135 | SheetContent,
136 | SheetHeader,
137 | SheetFooter,
138 | SheetTitle,
139 | SheetDescription,
140 | }
141 |
--------------------------------------------------------------------------------
/hooks/use-toast.ts:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | // Inspired by react-hot-toast library
4 | import * as React from "react";
5 |
6 | import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
7 |
8 | const TOAST_LIMIT = 1;
9 | const TOAST_REMOVE_DELAY = 1000000;
10 |
11 | type ToasterToast = ToastProps & {
12 | id: string;
13 | title?: React.ReactNode;
14 | description?: React.ReactNode;
15 | action?: ToastActionElement;
16 | };
17 |
18 | const actionTypes = {
19 | ADD_TOAST: "ADD_TOAST",
20 | UPDATE_TOAST: "UPDATE_TOAST",
21 | DISMISS_TOAST: "DISMISS_TOAST",
22 | REMOVE_TOAST: "REMOVE_TOAST",
23 | } as const;
24 |
25 | let count = 0;
26 |
27 | function genId() {
28 | count = (count + 1) % Number.MAX_SAFE_INTEGER;
29 | return count.toString();
30 | }
31 |
32 | type ActionType = typeof actionTypes;
33 |
34 | type Action =
35 | | {
36 | type: ActionType["ADD_TOAST"];
37 | toast: ToasterToast;
38 | }
39 | | {
40 | type: ActionType["UPDATE_TOAST"];
41 | toast: Partial;
42 | }
43 | | {
44 | type: ActionType["DISMISS_TOAST"];
45 | toastId?: ToasterToast["id"];
46 | }
47 | | {
48 | type: ActionType["REMOVE_TOAST"];
49 | toastId?: ToasterToast["id"];
50 | };
51 |
52 | interface State {
53 | toasts: ToasterToast[];
54 | }
55 |
56 | const toastTimeouts = new Map>();
57 |
58 | const addToRemoveQueue = (toastId: string) => {
59 | if (toastTimeouts.has(toastId)) {
60 | return;
61 | }
62 |
63 | const timeout = setTimeout(() => {
64 | toastTimeouts.delete(toastId);
65 | dispatch({
66 | type: "REMOVE_TOAST",
67 | toastId: toastId,
68 | });
69 | }, TOAST_REMOVE_DELAY);
70 |
71 | toastTimeouts.set(toastId, timeout);
72 | };
73 |
74 | export const reducer = (state: State, action: Action): State => {
75 | switch (action.type) {
76 | case "ADD_TOAST":
77 | return {
78 | ...state,
79 | toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
80 | };
81 |
82 | case "UPDATE_TOAST":
83 | return {
84 | ...state,
85 | toasts: state.toasts.map((t) =>
86 | t.id === action.toast.id ? { ...t, ...action.toast } : t
87 | ),
88 | };
89 |
90 | case "DISMISS_TOAST": {
91 | const { toastId } = action;
92 |
93 | // ! Side effects ! - This could be extracted into a dismissToast() action,
94 | // but I'll keep it here for simplicity
95 | if (toastId) {
96 | addToRemoveQueue(toastId);
97 | } else {
98 | state.toasts.forEach((toast) => {
99 | addToRemoveQueue(toast.id);
100 | });
101 | }
102 |
103 | return {
104 | ...state,
105 | toasts: state.toasts.map((t) =>
106 | t.id === toastId || toastId === undefined
107 | ? {
108 | ...t,
109 | open: false,
110 | }
111 | : t
112 | ),
113 | };
114 | }
115 | case "REMOVE_TOAST":
116 | if (action.toastId === undefined) {
117 | return {
118 | ...state,
119 | toasts: [],
120 | };
121 | }
122 | return {
123 | ...state,
124 | toasts: state.toasts.filter((t) => t.id !== action.toastId),
125 | };
126 | }
127 | };
128 |
129 | const listeners: Array<(state: State) => void> = [];
130 |
131 | let memoryState: State = { toasts: [] };
132 |
133 | function dispatch(action: Action) {
134 | memoryState = reducer(memoryState, action);
135 | listeners.forEach((listener) => {
136 | listener(memoryState);
137 | });
138 | }
139 |
140 | type Toast = Omit;
141 |
142 | function toast({ ...props }: Toast) {
143 | const id = genId();
144 |
145 | const update = (props: ToasterToast) =>
146 | dispatch({
147 | type: "UPDATE_TOAST",
148 | toast: { ...props, id },
149 | });
150 | const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
151 |
152 | dispatch({
153 | type: "ADD_TOAST",
154 | toast: {
155 | ...props,
156 | id,
157 | open: true,
158 | onOpenChange: (open) => {
159 | if (!open) dismiss();
160 | },
161 | },
162 | });
163 |
164 | return {
165 | id: id,
166 | dismiss,
167 | update,
168 | };
169 | }
170 |
171 | function useToast() {
172 | const [state, setState] = React.useState(memoryState);
173 |
174 | React.useEffect(() => {
175 | listeners.push(setState);
176 | return () => {
177 | const index = listeners.indexOf(setState);
178 | if (index > -1) {
179 | listeners.splice(index, 1);
180 | }
181 | };
182 | }, [state]);
183 |
184 | return {
185 | ...state,
186 | toast,
187 | dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
188 | };
189 | }
190 |
191 | export { useToast, toast };
192 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SheetPrimitive from "@radix-ui/react-dialog"
5 | import { Cross2Icon } from "@radix-ui/react-icons"
6 | import { cva, type VariantProps } from "class-variance-authority"
7 |
8 | import { cn } from "@/lib/utils"
9 |
10 | const Sheet = SheetPrimitive.Root
11 |
12 | const SheetTrigger = SheetPrimitive.Trigger
13 |
14 | const SheetClose = SheetPrimitive.Close
15 |
16 | const SheetPortal = SheetPrimitive.Portal
17 |
18 | const SheetOverlay = React.forwardRef<
19 | React.ElementRef,
20 | React.ComponentPropsWithoutRef
21 | >(({ className, ...props }, ref) => (
22 |
30 | ))
31 | SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
32 |
33 | const sheetVariants = cva(
34 | "fixed z-50 gap-4 bg-background p-6 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",
35 | {
36 | variants: {
37 | side: {
38 | top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
39 | bottom:
40 | "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
41 | 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",
42 | right:
43 | "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
44 | },
45 | },
46 | defaultVariants: {
47 | side: "right",
48 | },
49 | }
50 | )
51 |
52 | interface SheetContentProps
53 | extends React.ComponentPropsWithoutRef,
54 | VariantProps { }
55 |
56 | const SheetContent = React.forwardRef<
57 | React.ElementRef,
58 | SheetContentProps
59 | >(({ side = "right", className, children, ...props }, ref) => (
60 |
61 |
62 |
67 |
68 |
69 | Close
70 |
71 | {children}
72 |
73 |
74 | ))
75 | SheetContent.displayName = SheetPrimitive.Content.displayName
76 |
77 | const SheetHeader = ({
78 | className,
79 | ...props
80 | }: React.HTMLAttributes) => (
81 |
88 | )
89 | SheetHeader.displayName = "SheetHeader"
90 |
91 | const SheetFooter = ({
92 | className,
93 | ...props
94 | }: React.HTMLAttributes) => (
95 |
102 | )
103 | SheetFooter.displayName = "SheetFooter"
104 |
105 | const SheetTitle = React.forwardRef<
106 | React.ElementRef,
107 | React.ComponentPropsWithoutRef
108 | >(({ className, ...props }, ref) => (
109 |
114 | ))
115 | SheetTitle.displayName = SheetPrimitive.Title.displayName
116 |
117 | const SheetDescription = React.forwardRef<
118 | React.ElementRef,
119 | React.ComponentPropsWithoutRef
120 | >(({ className, ...props }, ref) => (
121 |
126 | ))
127 | SheetDescription.displayName = SheetPrimitive.Description.displayName
128 |
129 | export {
130 | Sheet,
131 | SheetPortal,
132 | SheetOverlay,
133 | SheetTrigger,
134 | SheetClose,
135 | SheetContent,
136 | SheetHeader,
137 | SheetFooter,
138 | SheetTitle,
139 | SheetDescription,
140 | }
141 |
--------------------------------------------------------------------------------
/components/ui/form.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { Slot } from "@radix-ui/react-slot"
6 | import {
7 | Controller,
8 | ControllerProps,
9 | FieldPath,
10 | FieldValues,
11 | FormProvider,
12 | useFormContext,
13 | } from "react-hook-form"
14 |
15 | import { cn } from "@/lib/utils"
16 | import { Label } from "@/components/ui/label"
17 |
18 | const Form = FormProvider
19 |
20 | type FormFieldContextValue<
21 | TFieldValues extends FieldValues = FieldValues,
22 | TName extends FieldPath = FieldPath
23 | > = {
24 | name: TName
25 | }
26 |
27 | const FormFieldContext = React.createContext(
28 | {} as FormFieldContextValue
29 | )
30 |
31 | const FormField = <
32 | TFieldValues extends FieldValues = FieldValues,
33 | TName extends FieldPath = FieldPath
34 | >({
35 | ...props
36 | }: ControllerProps) => {
37 | return (
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | const useFormField = () => {
45 | const fieldContext = React.useContext(FormFieldContext)
46 | const itemContext = React.useContext(FormItemContext)
47 | const { getFieldState, formState } = useFormContext()
48 |
49 | const fieldState = getFieldState(fieldContext.name, formState)
50 |
51 | if (!fieldContext) {
52 | throw new Error("useFormField should be used within ")
53 | }
54 |
55 | const { id } = itemContext
56 |
57 | return {
58 | id,
59 | name: fieldContext.name,
60 | formItemId: `${id}-form-item`,
61 | formDescriptionId: `${id}-form-item-description`,
62 | formMessageId: `${id}-form-item-message`,
63 | ...fieldState,
64 | }
65 | }
66 |
67 | type FormItemContextValue = {
68 | id: string
69 | }
70 |
71 | const FormItemContext = React.createContext(
72 | {} as FormItemContextValue
73 | )
74 |
75 | const FormItem = React.forwardRef<
76 | HTMLDivElement,
77 | React.HTMLAttributes
78 | >(({ className, ...props }, ref) => {
79 | const id = React.useId()
80 |
81 | return (
82 |
83 |
84 |
85 | )
86 | })
87 | FormItem.displayName = "FormItem"
88 |
89 | const FormLabel = React.forwardRef<
90 | React.ElementRef,
91 | React.ComponentPropsWithoutRef
92 | >(({ className, ...props }, ref) => {
93 | const { error, formItemId } = useFormField()
94 |
95 | return (
96 |
102 | )
103 | })
104 | FormLabel.displayName = "FormLabel"
105 |
106 | const FormControl = React.forwardRef<
107 | React.ElementRef,
108 | React.ComponentPropsWithoutRef
109 | >(({ ...props }, ref) => {
110 | const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
111 |
112 | return (
113 |
124 | )
125 | })
126 | FormControl.displayName = "FormControl"
127 |
128 | const FormDescription = React.forwardRef<
129 | HTMLParagraphElement,
130 | React.HTMLAttributes
131 | >(({ className, ...props }, ref) => {
132 | const { formDescriptionId } = useFormField()
133 |
134 | return (
135 |
141 | )
142 | })
143 | FormDescription.displayName = "FormDescription"
144 |
145 | const FormMessage = React.forwardRef<
146 | HTMLParagraphElement,
147 | React.HTMLAttributes
148 | >(({ className, children, ...props }, ref) => {
149 | const { error, formMessageId } = useFormField()
150 | const body = error ? String(error?.message) : children
151 |
152 | if (!body) {
153 | return null
154 | }
155 |
156 | return (
157 |
163 | {body}
164 |
165 | )
166 | })
167 | FormMessage.displayName = "FormMessage"
168 |
169 | export {
170 | useFormField,
171 | Form,
172 | FormItem,
173 | FormLabel,
174 | FormControl,
175 | FormDescription,
176 | FormMessage,
177 | FormField,
178 | }
179 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/form.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { Slot } from "@radix-ui/react-slot"
6 | import {
7 | Controller,
8 | ControllerProps,
9 | FieldPath,
10 | FieldValues,
11 | FormProvider,
12 | useFormContext,
13 | } from "react-hook-form"
14 |
15 | import { cn } from "@/lib/utils"
16 | import { Label } from "@shadcn-fullcalender/ui/label"
17 |
18 | const Form = FormProvider
19 |
20 | type FormFieldContextValue<
21 | TFieldValues extends FieldValues = FieldValues,
22 | TName extends FieldPath = FieldPath
23 | > = {
24 | name: TName
25 | }
26 |
27 | const FormFieldContext = React.createContext(
28 | {} as FormFieldContextValue
29 | )
30 |
31 | const FormField = <
32 | TFieldValues extends FieldValues = FieldValues,
33 | TName extends FieldPath = FieldPath
34 | >({
35 | ...props
36 | }: ControllerProps) => {
37 | return (
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | const useFormField = () => {
45 | const fieldContext = React.useContext(FormFieldContext)
46 | const itemContext = React.useContext(FormItemContext)
47 | const { getFieldState, formState } = useFormContext()
48 |
49 | const fieldState = getFieldState(fieldContext.name, formState)
50 |
51 | if (!fieldContext) {
52 | throw new Error("useFormField should be used within ")
53 | }
54 |
55 | const { id } = itemContext
56 |
57 | return {
58 | id,
59 | name: fieldContext.name,
60 | formItemId: `${id}-form-item`,
61 | formDescriptionId: `${id}-form-item-description`,
62 | formMessageId: `${id}-form-item-message`,
63 | ...fieldState,
64 | }
65 | }
66 |
67 | type FormItemContextValue = {
68 | id: string
69 | }
70 |
71 | const FormItemContext = React.createContext(
72 | {} as FormItemContextValue
73 | )
74 |
75 | const FormItem = React.forwardRef<
76 | HTMLDivElement,
77 | React.HTMLAttributes
78 | >(({ className, ...props }, ref) => {
79 | const id = React.useId()
80 |
81 | return (
82 |
83 |
84 |
85 | )
86 | })
87 | FormItem.displayName = "FormItem"
88 |
89 | const FormLabel = React.forwardRef<
90 | React.ElementRef,
91 | React.ComponentPropsWithoutRef
92 | >(({ className, ...props }, ref) => {
93 | const { error, formItemId } = useFormField()
94 |
95 | return (
96 |
102 | )
103 | })
104 | FormLabel.displayName = "FormLabel"
105 |
106 | const FormControl = React.forwardRef<
107 | React.ElementRef,
108 | React.ComponentPropsWithoutRef
109 | >(({ ...props }, ref) => {
110 | const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
111 |
112 | return (
113 |
124 | )
125 | })
126 | FormControl.displayName = "FormControl"
127 |
128 | const FormDescription = React.forwardRef<
129 | HTMLParagraphElement,
130 | React.HTMLAttributes
131 | >(({ className, ...props }, ref) => {
132 | const { formDescriptionId } = useFormField()
133 |
134 | return (
135 |
141 | )
142 | })
143 | FormDescription.displayName = "FormDescription"
144 |
145 | const FormMessage = React.forwardRef<
146 | HTMLParagraphElement,
147 | React.HTMLAttributes
148 | >(({ className, children, ...props }, ref) => {
149 | const { error, formMessageId } = useFormField()
150 | const body = error ? String(error?.message) : children
151 |
152 | if (!body) {
153 | return null
154 | }
155 |
156 | return (
157 |
163 | {body}
164 |
165 | )
166 | })
167 | FormMessage.displayName = "FormMessage"
168 |
169 | export {
170 | useFormField,
171 | Form,
172 | FormItem,
173 | FormLabel,
174 | FormControl,
175 | FormDescription,
176 | FormMessage,
177 | FormField,
178 | }
179 |
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { Slot, Slottable } from "@radix-ui/react-slot";
3 | import { cva, type VariantProps } from "class-variance-authority";
4 | import { cn } from "@/lib/utils";
5 |
6 | const buttonVariants = cva(
7 | "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",
8 | {
9 | variants: {
10 | variant: {
11 | default: "bg-primary text-primary-foreground hover:bg-primary/90",
12 | destructive:
13 | "bg-destructive text-destructive-foreground hover:bg-destructive/90",
14 | outline:
15 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
16 | secondary:
17 | "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18 | ghost: "hover:bg-accent hover:text-accent-foreground",
19 | link: "text-primary underline-offset-4 hover:underline",
20 | expandIcon:
21 | "group relative text-primary-foreground bg-primary hover:bg-primary/90",
22 | ringHover:
23 | "bg-primary text-primary-foreground transition-all duration-300 hover:bg-primary/90 hover:ring-2 hover:ring-primary/90 hover:ring-offset-2",
24 | shine:
25 | "text-primary-foreground animate-shine bg-gradient-to-r from-primary via-primary/75 to-primary bg-[length:400%_100%] ",
26 | gooeyRight:
27 | "text-primary-foreground relative bg-primary 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-400 before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%] ",
28 | gooeyLeft:
29 | "text-primary-foreground relative bg-primary 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-400 after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%] ",
30 | linkHover1:
31 | "relative after:absolute after:bg-primary 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",
32 | linkHover2:
33 | "relative after:absolute after:bg-primary 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",
34 | },
35 | size: {
36 | default: "h-10 px-4 py-2",
37 | sm: "h-9 rounded-md px-3",
38 | lg: "h-11 rounded-md px-8",
39 | icon: "h-10 w-10",
40 | },
41 | },
42 | defaultVariants: {
43 | variant: "default",
44 | size: "default",
45 | },
46 | }
47 | );
48 |
49 | interface IconProps {
50 | Icon: React.ElementType;
51 | iconPlacement: "left" | "right";
52 | }
53 |
54 | interface IconRefProps {
55 | Icon?: never;
56 | iconPlacement?: undefined;
57 | }
58 |
59 | export interface ButtonProps
60 | extends React.ButtonHTMLAttributes,
61 | VariantProps {
62 | asChild?: boolean;
63 | }
64 |
65 | export type ButtonIconProps = IconProps | IconRefProps;
66 |
67 | const Button = React.forwardRef<
68 | HTMLButtonElement,
69 | ButtonProps & ButtonIconProps
70 | >(
71 | (
72 | {
73 | className,
74 | variant,
75 | size,
76 | asChild = false,
77 | Icon,
78 | iconPlacement,
79 | ...props
80 | },
81 | ref
82 | ) => {
83 | const Comp = asChild ? Slot : "button";
84 | return (
85 |
90 | {Icon && iconPlacement === "left" && (
91 |
92 |
93 |
94 | )}
95 | {props.children}
96 | {Icon && iconPlacement === "right" && (
97 |
98 |
99 |
100 | )}
101 |
102 | );
103 | }
104 | );
105 | Button.displayName = "Button";
106 |
107 | export { Button, buttonVariants };
108 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { Slot, Slottable } from "@radix-ui/react-slot";
3 | import { cva, type VariantProps } from "class-variance-authority";
4 | import { cn } from "@/lib/utils";
5 |
6 | const buttonVariants = cva(
7 | "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",
8 | {
9 | variants: {
10 | variant: {
11 | default: "bg-primary text-primary-foreground hover:bg-primary/90",
12 | destructive:
13 | "bg-destructive text-destructive-foreground hover:bg-destructive/90",
14 | outline:
15 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
16 | secondary:
17 | "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18 | ghost: "hover:bg-accent hover:text-accent-foreground",
19 | link: "text-primary underline-offset-4 hover:underline",
20 | expandIcon:
21 | "group relative text-primary-foreground bg-primary hover:bg-primary/90",
22 | ringHover:
23 | "bg-primary text-primary-foreground transition-all duration-300 hover:bg-primary/90 hover:ring-2 hover:ring-primary/90 hover:ring-offset-2",
24 | shine:
25 | "text-primary-foreground animate-shine bg-gradient-to-r from-primary via-primary/75 to-primary bg-[length:400%_100%] ",
26 | gooeyRight:
27 | "text-primary-foreground relative bg-primary 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-400 before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%] ",
28 | gooeyLeft:
29 | "text-primary-foreground relative bg-primary 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-400 after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%] ",
30 | linkHover1:
31 | "relative after:absolute after:bg-primary 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",
32 | linkHover2:
33 | "relative after:absolute after:bg-primary 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",
34 | },
35 | size: {
36 | default: "h-10 px-4 py-2",
37 | sm: "h-9 rounded-md px-3",
38 | lg: "h-11 rounded-md px-8",
39 | icon: "h-10 w-10",
40 | },
41 | },
42 | defaultVariants: {
43 | variant: "default",
44 | size: "default",
45 | },
46 | }
47 | );
48 |
49 | interface IconProps {
50 | Icon: React.ElementType;
51 | iconPlacement: "left" | "right";
52 | }
53 |
54 | interface IconRefProps {
55 | Icon?: never;
56 | iconPlacement?: undefined;
57 | }
58 |
59 | export interface ButtonProps
60 | extends React.ButtonHTMLAttributes,
61 | VariantProps {
62 | asChild?: boolean;
63 | }
64 |
65 | export type ButtonIconProps = IconProps | IconRefProps;
66 |
67 | const Button = React.forwardRef<
68 | HTMLButtonElement,
69 | ButtonProps & ButtonIconProps
70 | >(
71 | (
72 | {
73 | className,
74 | variant,
75 | size,
76 | asChild = false,
77 | Icon,
78 | iconPlacement,
79 | ...props
80 | },
81 | ref
82 | ) => {
83 | const Comp = asChild ? Slot : "button";
84 | return (
85 |
90 | {Icon && iconPlacement === "left" && (
91 |
92 |
93 |
94 | )}
95 | {props.children}
96 | {Icon && iconPlacement === "right" && (
97 |
98 |
99 |
100 | )}
101 |
102 | );
103 | }
104 | );
105 | Button.displayName = "Button";
106 |
107 | export { Button, buttonVariants };
108 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/calender-components/yearview.tsx:
--------------------------------------------------------------------------------
1 | import ListAllEvents from "@shadcn-fullcalender/event-components/listallevents";
2 | import { Event } from "@shadcn-fullcalender/types/event";
3 | import {
4 | addDays,
5 | eachDayOfInterval,
6 | endOfMonth,
7 | format,
8 | parseISO,
9 | startOfMonth,
10 | subDays,
11 | } from "date-fns";
12 | import React from "react";
13 |
14 |
15 | interface YearViewProps {
16 | currentDate: Date; // Current date
17 | events: Event[]; // Array of events
18 | }
19 |
20 |
21 |
22 | const YearView: React.FC = ({ currentDate, events }) => {
23 | // Define the color map for event types
24 |
25 | // Generate dates for each month in the year, including leading and trailing days
26 | const generateDatesForMonth = (month: number) => {
27 | const start = startOfMonth(new Date(currentDate.getFullYear(), month));
28 | const end = endOfMonth(start);
29 |
30 | // Get the day of the week the month starts and ends on
31 | const startDayOfWeek = start.getDay(); // 0 = Sunday, 6 = Saturday
32 | const endDayOfWeek = end.getDay();
33 |
34 | // Calculate leading days from the previous month
35 | const leadingDays =
36 | startDayOfWeek > 0
37 | ? eachDayOfInterval({
38 | start: subDays(start, startDayOfWeek),
39 | end: subDays(start, 1),
40 | })
41 | : [];
42 |
43 | // Calculate trailing days from the next month
44 | const trailingDays =
45 | endDayOfWeek < 6
46 | ? eachDayOfInterval({
47 | start: addDays(end, 1),
48 | end: addDays(end, 6 - endDayOfWeek),
49 | })
50 | : [];
51 |
52 | // Combine leading days, current month's days, and trailing days
53 | return [
54 | ...leadingDays,
55 | ...eachDayOfInterval({ start, end }),
56 | ...trailingDays,
57 | ];
58 | };
59 |
60 | const daysOfWeek = ["S", "M", "T", "W", "T", "F", "S"]; // Days of the week
61 |
62 | // Create an array of months with their names and dates
63 | const months = Array.from({ length: 12 }, (_, i) => {
64 | const monthName = format(new Date(currentDate.getFullYear(), i), "MMMM");
65 | const dates = generateDatesForMonth(i);
66 | return { monthName, dates };
67 | });
68 |
69 | // Check if a date is today
70 | const isToday = (date: Date) => {
71 | const today = new Date();
72 | return (
73 | date.getDate() === today.getDate() &&
74 | date.getMonth() === today.getMonth() &&
75 | date.getFullYear() === today.getFullYear()
76 | );
77 | };
78 |
79 | // Check if a date belongs to the current month
80 | const isCurrentMonth = (date: Date, month: number) => {
81 | return date.getMonth() === month;
82 | };
83 |
84 | // Create a function to get the events for a specific date
85 | const getEventsForDate = (date: Date) => {
86 | const formattedDate = format(date, "yyyy-MM-dd");
87 |
88 | return events.filter((event: Event) => {
89 | const startDate = format(parseISO(event.startdate), "yyyy-MM-dd");
90 | const endDate = format(parseISO(event.enddate), "yyyy-MM-dd");
91 |
92 | if (startDate === endDate) {
93 | return startDate === formattedDate;
94 | } else {
95 | return formattedDate >= startDate && formattedDate <= endDate;
96 | }
97 | });
98 | };
99 |
100 |
101 | return (
102 |
103 |
104 | {months.map((month, index) => (
105 |
106 |
107 | {month.monthName}
108 |
109 | {/* Render the days of the week once */}
110 |
111 | {daysOfWeek.map((day, index) => (
112 |
113 | {day}
114 |
115 | ))}
116 |
117 | {/* Render the dates, including leading and trailing days */}
118 |
119 | {month.dates.map((date) => {
120 | const eventsForDate = getEventsForDate(date);
121 | return (
122 |
130 | );
131 | })}
132 |
133 |
134 | ))}
135 |
136 |
137 | );
138 | };
139 |
140 | export default YearView;
141 |
142 | // Sample events for testing
143 |
--------------------------------------------------------------------------------
/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5 |
6 | import { cn } from "@/lib/utils"
7 | import { buttonVariants } from "@/components/ui/button"
8 |
9 | const AlertDialog = AlertDialogPrimitive.Root
10 |
11 | const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12 |
13 | const AlertDialogPortal = AlertDialogPrimitive.Portal
14 |
15 | const AlertDialogOverlay = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, ...props }, ref) => (
19 |
27 | ))
28 | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
29 |
30 | const AlertDialogContent = React.forwardRef<
31 | React.ElementRef,
32 | React.ComponentPropsWithoutRef
33 | >(({ className, ...props }, ref) => (
34 |
35 |
36 |
44 |
45 | ))
46 | AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
47 |
48 | const AlertDialogHeader = ({
49 | className,
50 | ...props
51 | }: React.HTMLAttributes) => (
52 |
59 | )
60 | AlertDialogHeader.displayName = "AlertDialogHeader"
61 |
62 | const AlertDialogFooter = ({
63 | className,
64 | ...props
65 | }: React.HTMLAttributes) => (
66 |
73 | )
74 | AlertDialogFooter.displayName = "AlertDialogFooter"
75 |
76 | const AlertDialogTitle = React.forwardRef<
77 | React.ElementRef,
78 | React.ComponentPropsWithoutRef
79 | >(({ className, ...props }, ref) => (
80 |
85 | ))
86 | AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
87 |
88 | const AlertDialogDescription = React.forwardRef<
89 | React.ElementRef,
90 | React.ComponentPropsWithoutRef
91 | >(({ className, ...props }, ref) => (
92 |
97 | ))
98 | AlertDialogDescription.displayName =
99 | AlertDialogPrimitive.Description.displayName
100 |
101 | const AlertDialogAction = React.forwardRef<
102 | React.ElementRef,
103 | React.ComponentPropsWithoutRef
104 | >(({ className, ...props }, ref) => (
105 |
110 | ))
111 | AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
112 |
113 | const AlertDialogCancel = React.forwardRef<
114 | React.ElementRef,
115 | React.ComponentPropsWithoutRef
116 | >(({ className, ...props }, ref) => (
117 |
126 | ))
127 | AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
128 |
129 | export {
130 | AlertDialog,
131 | AlertDialogPortal,
132 | AlertDialogOverlay,
133 | AlertDialogTrigger,
134 | AlertDialogContent,
135 | AlertDialogHeader,
136 | AlertDialogFooter,
137 | AlertDialogTitle,
138 | AlertDialogDescription,
139 | AlertDialogAction,
140 | AlertDialogCancel,
141 | }
142 |
--------------------------------------------------------------------------------
/shadcn-fullcalender/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5 |
6 | import { cn } from "@/lib/utils"
7 | import { buttonVariants } from "@shadcn-fullcalender/ui/button"
8 |
9 | const AlertDialog = AlertDialogPrimitive.Root
10 |
11 | const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12 |
13 | const AlertDialogPortal = AlertDialogPrimitive.Portal
14 |
15 | const AlertDialogOverlay = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, ...props }, ref) => (
19 |
27 | ))
28 | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
29 |
30 | const AlertDialogContent = React.forwardRef<
31 | React.ElementRef,
32 | React.ComponentPropsWithoutRef
33 | >(({ className, ...props }, ref) => (
34 |
35 |