From a42317fb22b8eecce51c73f9494530f46055a3ca Mon Sep 17 00:00:00 2001
From: Paribesh Nepal <nepalparibesh01@gmail.com>
Date: Tue, 15 Oct 2024 00:54:29 +0530
Subject: [PATCH] feat: ui change for the calender

---
 package.json                   |   3 +
 src/components/job-form.tsx    | 121 +++++++++++++++++++--------------
 src/components/ui/calendar.tsx |  66 ++++++++++++++++++
 3 files changed, 139 insertions(+), 51 deletions(-)
 create mode 100644 src/components/ui/calendar.tsx

diff --git a/package.json b/package.json
index a97eb2f2..c6562990 100644
--- a/package.json
+++ b/package.json
@@ -54,10 +54,12 @@
     "@types/lodash": "^4.17.7",
     "@types/uuid": "^10.0.0",
     "@uidotdev/usehooks": "^2.4.1",
+    "100xdevs-job-board": "file:",
     "bcryptjs": "^2.4.3",
     "class-variance-authority": "^0.7.0",
     "clsx": "^2.1.1",
     "cmdk": "^1.0.0",
+    "date-fns": "^2.30.0",
     "dayjs": "^1.11.13",
     "framer-motion": "^11.9.0",
     "jiti": "^1.21.6",
@@ -71,6 +73,7 @@
     "node-cron": "^3.0.3",
     "nodemailer": "^6.9.15",
     "react": "^18",
+    "react-day-picker": "^8.10.1",
     "react-dom": "^18",
     "react-hook-form": "^7.52.2",
     "react-icons": "^5.2.1",
diff --git a/src/components/job-form.tsx b/src/components/job-form.tsx
index add6f3b4..55ffa36a 100644
--- a/src/components/job-form.tsx
+++ b/src/components/job-form.tsx
@@ -25,7 +25,12 @@ import {
 import { Button } from './ui/button';
 import { Input } from './ui/input';
 import { useToast } from './ui/use-toast';
-import { Calendar, LucideRocket, MailOpenIcon, X } from 'lucide-react';
+import {
+  Calendar as CalendarIcon,
+  LucideRocket,
+  MailOpenIcon,
+  X,
+} from 'lucide-react';
 import DescriptionEditor from './DescriptionEditor';
 import Image from 'next/image';
 import { FaFileUpload } from 'react-icons/fa';
@@ -33,6 +38,7 @@ import { Switch } from './ui/switch';
 import { Label } from './ui/label';
 import dynamic from 'next/dynamic';
 import { uploadFileAction } from '@/actions/upload-to-cdn';
+import { format } from 'date-fns';
 
 const DynamicGmapsAutoSuggest = dynamic(() => import('./gmaps-autosuggest'), {
   ssr: false,
@@ -43,6 +49,8 @@ import { useSession } from 'next-auth/react';
 import { useRouter } from 'next/navigation';
 import APP_PATHS from '@/config/path.config';
 import { SkillsCombobox } from './skills-combobox';
+import { Popover, PopoverContent, PopoverTrigger } from './ui/popover';
+import { Calendar } from '@/components/ui/calendar';
 
 const PostJobForm = () => {
   const session = useSession();
@@ -203,7 +211,7 @@ const PostJobForm = () => {
     <div className="flex flex-col items-center w-[30rem] gap-y-10 justify-center mb-20">
       <div className="w-full md:justify-center mt-4 flex flex-col md:flex-row gap-2">
         <div className="bg-gray-800/90 backdrop-blur-sm p-4 rounded-lg text-center text-white w-full md:w-48">
-          <Calendar className="w-8 h-8 mb-3 mx-auto text-green-500" />
+          <CalendarIcon className="w-8 h-8 mb-3 mx-auto text-green-500" />
           <p className="text-base font-semibold mb-1">Posted for</p>
           <p className="text-gray-400 text-sm">30 days</p>
         </div>
@@ -509,65 +517,76 @@ const PostJobForm = () => {
                   )}
                 </div>
               </div>
-              <div className="flex flex-col-2 gap-2">
-                <div className="flex flex-col gap-2">
-                  <div className="">
-                    <Label>Expiry date</Label>
-                  </div>
-                  <div>
+              <div className="flex flex-col gap-2">
+                <Label>Expiry date</Label>
+                <FormField
+                  control={form.control}
+                  name="hasExpiryDate"
+                  render={({ field }) => (
+                    <FormItem className="flex items-center space-y-0 gap-2">
+                      <FormControl>
+                        <Switch
+                          checked={field.value}
+                          onCheckedChange={field.onChange}
+                          className="data-[state=checked]:bg-gray-300 data-[state=unchecked]:bg-gray-400"
+                        />
+                      </FormControl>
+                      <FormLabel className="mt-0">
+                        Does this job posting have an expiry date?
+                      </FormLabel>
+                    </FormItem>
+                  )}
+                />
+
+                {watchHasExpiryDate && (
+                  <div className="flex gap-4">
                     <FormField
                       control={form.control}
-                      name="hasExpiryDate"
+                      name="expiryDate"
                       render={({ field }) => (
-                        <FormItem className="flex items-center space-y-0 gap-2">
+                        <FormItem className="flex-1">
+                          <div className="space-y-0.5"></div>
                           <FormControl>
-                            <Switch
-                              checked={field.value}
-                              onCheckedChange={field.onChange}
-                              className="data-[state=checked]:bg-gray-300 data-[state=unchecked]:bg-gray-400"
-                            />
+                            <Popover>
+                              <PopoverTrigger asChild>
+                                <Button
+                                  variant="outline"
+                                  className={`w-[240px] pl-3 text-left font-normal bg-gray-800 
+                                      `} // No color change on hover
+                                >
+                                  {field.value ? (
+                                    format(new Date(field.value), 'PPP')
+                                  ) : (
+                                    <span>Pick a date</span>
+                                  )}
+                                  <span className="ml-auto">📅</span>
+                                </Button>
+                              </PopoverTrigger>
+                              <PopoverContent
+                                className="w-auto p-0"
+                                align="start"
+                              >
+                                <Calendar
+                                  mode="single"
+                                  aria-selected={field.value}
+                                  onSelect={(date: any) => {
+                                    field.onChange(date); // Update the field value with the selected date
+                                  }}
+                                  aria-disabled={(date: any) =>
+                                    date > new Date() ||
+                                    date < new Date('1900-01-01')
+                                  }
+                                />
+                              </PopoverContent>
+                            </Popover>
                           </FormControl>
-
-                          <FormLabel className="mt-0">
-                            Does this job posting have an expiry date?
-                          </FormLabel>
+                          <FormMessage />
                         </FormItem>
                       )}
                     />
                   </div>
-                  {watchHasExpiryDate && (
-                    <div className="flex gap-4">
-                      <FormField
-                        control={form.control}
-                        name="expiryDate"
-                        render={({ field }) => (
-                          <FormItem className="flex-1">
-                            <div className="space-y-0.5"></div>
-                            <FormControl>
-                              <Input
-                                {...field}
-                                type="date"
-                                className=" w-2/5- bg-gray-800 border-gray-400"
-                                placeholder="Select expiry date"
-                                value={
-                                  field.value
-                                    ? field.value.toISOString().split('T')[0]
-                                    : ''
-                                }
-                                onChange={(e) =>
-                                  field.onChange(new Date(e.target.value))
-                                }
-                              />
-                            </FormControl>
-                            <FormMessage />
-                          </FormItem>
-                        )}
-                      />
-                    </div>
-                  )}
-                </div>
+                )}
               </div>
-
               <div className="space-y-2">
                 <FormLabel className="font-medium">Location</FormLabel>
                 <DynamicGmapsAutoSuggest
diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx
new file mode 100644
index 00000000..b45df763
--- /dev/null
+++ b/src/components/ui/calendar.tsx
@@ -0,0 +1,66 @@
+'use client';
+
+import * as React from 'react';
+import { ChevronLeft, ChevronRight } from 'lucide-react';
+import { DayPicker } from 'react-day-picker';
+
+import { cn } from '@/lib/utils';
+import { buttonVariants } from '@/components/ui/button';
+
+export type CalendarProps = React.ComponentProps<typeof DayPicker>;
+
+function Calendar({
+  className,
+  classNames,
+  showOutsideDays = true,
+  ...props
+}: CalendarProps) {
+  return (
+    <DayPicker
+      showOutsideDays={showOutsideDays}
+      className={cn('p-3', className)}
+      classNames={{
+        months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
+        month: 'space-y-4',
+        caption: 'flex justify-center pt-1 relative items-center',
+        caption_label: 'text-sm font-medium',
+        nav: 'space-x-1 flex items-center',
+        nav_button: cn(
+          buttonVariants({ variant: 'outline' }),
+          'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'
+        ),
+        nav_button_previous: 'absolute left-1',
+        nav_button_next: 'absolute right-1',
+        table: 'w-full border-collapse space-y-1',
+        head_row: 'flex',
+        head_cell:
+          'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
+        row: 'flex w-full mt-2',
+        cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
+        day: cn(
+          buttonVariants({ variant: 'ghost' }),
+          'h-9 w-9 p-0 font-normal aria-selected:opacity-100'
+        ),
+        day_range_end: 'day-range-end',
+        day_selected:
+          'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
+        day_today: 'bg-accent text-accent-foreground',
+        day_outside:
+          'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
+        day_disabled: 'text-muted-foreground opacity-50',
+        day_range_middle:
+          'aria-selected:bg-accent aria-selected:text-accent-foreground',
+        day_hidden: 'invisible',
+        ...classNames,
+      }}
+      components={{
+        IconLeft: () => <ChevronLeft className="h-4 w-4" />,
+        IconRight: () => <ChevronRight className="h-4 w-4" />,
+      }}
+      {...props}
+    />
+  );
+}
+Calendar.displayName = 'Calendar';
+
+export { Calendar };