mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-14 11:00:34 -06:00
fix: date picker ui-fix (#3382)
Co-authored-by: Jonas Höbenreich <64426524+jonas-hoebenreich@users.noreply.github.com> Co-authored-by: Vinay Kumar Maheshwaram <54681400+sudovinay01@users.noreply.github.com> Co-authored-by: Sharad Kushwaha <123795629+SharadK10@users.noreply.github.com> Co-authored-by: Matti Nannt <mail@matthiasnannt.com> Co-authored-by: Chase Nelson <Chase.a.nelson@gmail.com> Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com> Co-authored-by: Johannes <johannes@formbricks.com>
This commit is contained in:
@@ -334,7 +334,7 @@ export const ResponseOptionsCard = ({
|
||||
description="Automatically release the survey at the beginning of the day (UTC)."
|
||||
childBorder={true}>
|
||||
<div className="p-4">
|
||||
<DatePicker date={runOnDate} handleDateChange={handleRunOnDateChange} />
|
||||
<DatePicker date={runOnDate} updateSurveyDate={handleRunOnDateChange} />
|
||||
</div>
|
||||
</AdvancedOptionToggle>
|
||||
{/* Close Survey on Date */}
|
||||
@@ -346,7 +346,7 @@ export const ResponseOptionsCard = ({
|
||||
description="Automatically closes the survey at the beginning of the day (UTC)."
|
||||
childBorder={true}>
|
||||
<div className="p-4">
|
||||
<DatePicker date={closeOnDate} handleDateChange={handleCloseOnDateChange} />
|
||||
<DatePicker date={closeOnDate} updateSurveyDate={handleCloseOnDateChange} />
|
||||
</div>
|
||||
</AdvancedOptionToggle>
|
||||
|
||||
|
||||
@@ -1,54 +1,111 @@
|
||||
"use client";
|
||||
|
||||
import { format } from "date-fns";
|
||||
import { addDays } from "date-fns";
|
||||
import { CalendarIcon } from "lucide-react";
|
||||
import { useRef } from "react";
|
||||
import { SelectSingleEventHandler } from "react-day-picker";
|
||||
import { CalendarCheckIcon, CalendarIcon } from "lucide-react";
|
||||
import { useRef, useState } from "react";
|
||||
import Calendar from "react-calendar";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { Button } from "../Button";
|
||||
import { Calendar } from "../Calendar";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "../Popover";
|
||||
import "./styles.css";
|
||||
|
||||
export const DatePicker = ({
|
||||
date,
|
||||
handleDateChange,
|
||||
}: {
|
||||
date?: Date | null;
|
||||
handleDateChange: (date?: Date) => void;
|
||||
}) => {
|
||||
let formattedDate = date ? new Date(date) : undefined;
|
||||
const getOrdinalSuffix = (day: number) => {
|
||||
if (day > 3 && day < 21) return "th"; // 11th, 12th, 13th, etc.
|
||||
switch (day % 10) {
|
||||
case 1:
|
||||
return "st";
|
||||
case 2:
|
||||
return "nd";
|
||||
case 3:
|
||||
return "rd";
|
||||
default:
|
||||
return "th";
|
||||
}
|
||||
};
|
||||
|
||||
interface DatePickerProps {
|
||||
date: Date | null;
|
||||
updateSurveyDate: (date: Date) => void;
|
||||
}
|
||||
|
||||
export const DatePicker = ({ date, updateSurveyDate }: DatePickerProps) => {
|
||||
const [value, onChange] = useState<Date | undefined>(date ? new Date(date) : undefined);
|
||||
const [formattedDate, setFormattedDate] = useState<string | undefined>(
|
||||
date ? format(new Date(date), "do MMM, yyyy") : undefined
|
||||
);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const btnRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleDateSelect: SelectSingleEventHandler = (date) => {
|
||||
btnRef?.current?.click();
|
||||
handleDateChange(date);
|
||||
const onDateChange = (date: Date) => {
|
||||
if (date) {
|
||||
updateSurveyDate(date);
|
||||
const day = date.getDate();
|
||||
const ordinalSuffix = getOrdinalSuffix(day);
|
||||
const formatted = format(date, `d'${ordinalSuffix}' MMM, yyyy`);
|
||||
setFormattedDate(formatted);
|
||||
onChange(date);
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant={"minimal"}
|
||||
className={cn(
|
||||
"w-[280px] justify-start border border-slate-300 bg-white text-left font-normal",
|
||||
!formattedDate && "text-muted-foreground"
|
||||
)}
|
||||
ref={btnRef}>
|
||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||
{formattedDate ? format(formattedDate, "PPP") : <span>Pick a date</span>}
|
||||
</Button>
|
||||
{formattedDate ? (
|
||||
<Button
|
||||
variant={"minimal"}
|
||||
className={cn(
|
||||
"w-[280px] justify-start border border-slate-300 bg-white text-left font-normal transition-all ease-in hover:bg-slate-300",
|
||||
!formattedDate && "text-muted-foreground bg-slate-800"
|
||||
)}
|
||||
ref={btnRef}>
|
||||
<CalendarCheckIcon className="mr-2 h-4 w-4" />
|
||||
{formattedDate}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant={"minimal"}
|
||||
className={cn(
|
||||
"w-[280px] justify-start border border-slate-300 bg-white text-left font-normal hover:bg-slate-300",
|
||||
!formattedDate && "text-muted-foreground"
|
||||
)}
|
||||
onClick={() => setIsOpen(true)}
|
||||
ref={btnRef}>
|
||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||
<span>Pick a date</span>
|
||||
</Button>
|
||||
)}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0">
|
||||
<PopoverContent align="start" className="min-w-96 rounded-lg px-4 py-3">
|
||||
<Calendar
|
||||
autoFocus
|
||||
mode="single"
|
||||
selected={formattedDate}
|
||||
disabled={{
|
||||
before: addDays(new Date(), 1),
|
||||
value={value}
|
||||
onChange={(date) => onDateChange(date as Date)}
|
||||
minDate={new Date()}
|
||||
className="!border-0"
|
||||
tileClassName={({ date }: { date: Date }) => {
|
||||
const baseClass =
|
||||
"hover:fb-bg-input-bg-selected fb-rounded-custom fb-h-9 fb-p-0 fb-mt-1 fb-font-normal fb-text-heading aria-selected:fb-opacity-100 focus:fb-ring-2 focus:fb-bg-slate-200";
|
||||
// today's date class
|
||||
if (
|
||||
date.getDate() === new Date().getDate() &&
|
||||
date.getMonth() === new Date().getMonth() &&
|
||||
date.getFullYear() === new Date().getFullYear()
|
||||
) {
|
||||
return `${baseClass} !fb-bg-brand !fb-border-border-highlight !fb-text-heading focus:fb-ring-2 focus:fb-bg-slate-200`;
|
||||
}
|
||||
// active date class
|
||||
if (
|
||||
date.getDate() === value?.getDate() &&
|
||||
date.getMonth() === value?.getMonth() &&
|
||||
date.getFullYear() === value?.getFullYear()
|
||||
) {
|
||||
return `${baseClass} !fb-bg-brand !fb-border-border-highlight !fb-text-heading`;
|
||||
}
|
||||
|
||||
return baseClass;
|
||||
}}
|
||||
onSelect={handleDateSelect}
|
||||
showNeighboringMonth={false}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
53
packages/ui/components/DatePicker/styles.css
Normal file
53
packages/ui/components/DatePicker/styles.css
Normal file
@@ -0,0 +1,53 @@
|
||||
.react-calendar__navigation button {
|
||||
margin: 1% !important ;
|
||||
border-radius: 6%;
|
||||
}
|
||||
|
||||
.react-calendar__navigation button:disabled {
|
||||
background-color: var(--slate-100) !important;
|
||||
color: var(--slate-300) !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.react-calendar__navigation button:enabled:hover,
|
||||
.react-calendar__navigation button:enabled:focus {
|
||||
background-color: var(--slate-200) !important;
|
||||
}
|
||||
|
||||
.react-calendar__month-view__weekdays {
|
||||
text-decoration-style: dotted !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.react-calendar__month-view__days__day--weekend {
|
||||
color: var(--fb-brand) !important;
|
||||
}
|
||||
.react-calendar__tile:disabled {
|
||||
background-color: var(--slate-100) !important;
|
||||
color: var(--slate-400) !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.react-calendar__tile:enabled:hover,
|
||||
.react-calendar__tile:enabled:focus {
|
||||
background-color: var(--slate-200) !important;
|
||||
color: var(--slate-900) !important;
|
||||
}
|
||||
|
||||
.react-calendar__tile--now {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.react-calendar__tile .react-calendar__year-view__months__month {
|
||||
margin: 20px !important;
|
||||
background-color: var(--slate-100) !important;
|
||||
color: var(--slate-900) !important;
|
||||
}
|
||||
|
||||
.react-calendar__tile--hasActive {
|
||||
background-color: var(--fb-brand) !important;
|
||||
color: white !important;
|
||||
border-radius: 6% !important;
|
||||
}
|
||||
Reference in New Issue
Block a user