several changes
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
import { TextInput, Flex, Box, Button } from "@mantine/core";
|
||||
import { CalendarIcon } from "@phosphor-icons/react";
|
||||
import { useSheet } from "@/hooks/use-sheet";
|
||||
import Sheet from "@/components/sheet/sheet";
|
||||
import { DateTimePicker } from "../features/admin/components/date-time-picker";
|
||||
|
||||
interface DateInputProps {
|
||||
label: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
withAsterisk?: boolean;
|
||||
error?: React.ReactNode;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
// Date input that opens a sheet with mantine date time picker when clicked
|
||||
export const DateInputSheet = ({
|
||||
label,
|
||||
value,
|
||||
onChange,
|
||||
withAsterisk,
|
||||
error,
|
||||
placeholder
|
||||
}: DateInputProps) => {
|
||||
const sheet = useSheet();
|
||||
|
||||
const formatDisplayValue = (dateString: string) => {
|
||||
if (!dateString) return '';
|
||||
const date = new Date(dateString);
|
||||
if (isNaN(date.getTime())) return '';
|
||||
return date.toLocaleDateString('en-US', {
|
||||
weekday: 'short',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true
|
||||
});
|
||||
};
|
||||
|
||||
const handleDateChange = (newValue: string | null) => {
|
||||
onChange(newValue || '');
|
||||
sheet.close();
|
||||
};
|
||||
|
||||
const dateValue = value ? new Date(value) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextInput
|
||||
label={label}
|
||||
value={formatDisplayValue(value)}
|
||||
onClick={sheet.open}
|
||||
readOnly
|
||||
withAsterisk={withAsterisk}
|
||||
error={error}
|
||||
placeholder={placeholder || "Click to select date"}
|
||||
rightSection={<CalendarIcon size={16} />}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
|
||||
<Sheet {...sheet.props} title={`Select ${label}`}>
|
||||
<Flex gap='xs' direction='column' justify='center' p="md">
|
||||
<Box mx='auto'>
|
||||
<DateTimePicker
|
||||
value={dateValue}
|
||||
onChange={handleDateChange}
|
||||
/>
|
||||
</Box>
|
||||
<Button onClick={sheet.close} variant="subtle">
|
||||
Close
|
||||
</Button>
|
||||
</Flex>
|
||||
</Sheet>
|
||||
</>
|
||||
);
|
||||
};
|
||||
90
src/components/date-time-picker.tsx
Normal file
90
src/components/date-time-picker.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { DatePicker, TimeInput } from "@mantine/dates";
|
||||
import { ActionIcon, Stack } from "@mantine/core";
|
||||
import { useRef } from "react";
|
||||
import { ClockIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface DateTimePickerProps {
|
||||
value: Date | null;
|
||||
onChange: (date: string | null) => void;
|
||||
label?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const DateTimePicker = ({ value, onChange, label, ...rest }: DateTimePickerProps) => {
|
||||
const timeRef = useRef<HTMLInputElement>(null);
|
||||
const currentDate = value ? new Date(value) : null;
|
||||
|
||||
const formatDate = (date: Date | null): string => {
|
||||
if (!date) return "";
|
||||
return date.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
const formatTime = (date: Date | null): string => {
|
||||
if (!date) return "";
|
||||
return date.toTimeString().slice(0, 5);
|
||||
};
|
||||
|
||||
const handleDateChange = (dateString: string | null) => {
|
||||
if (!dateString) {
|
||||
onChange('');
|
||||
return;
|
||||
}
|
||||
|
||||
const newDate = new Date(dateString + 'T00:00:00');
|
||||
|
||||
if (currentDate) {
|
||||
newDate.setHours(currentDate.getHours());
|
||||
newDate.setMinutes(currentDate.getMinutes());
|
||||
}
|
||||
|
||||
onChange(newDate.toISOString());
|
||||
};
|
||||
|
||||
const handleTimeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const timeValue = event.target.value;
|
||||
if (!timeValue) return;
|
||||
|
||||
const [hours, minutes] = timeValue.split(':').map(Number);
|
||||
if (isNaN(hours) || isNaN(minutes)) return;
|
||||
|
||||
const baseDate = currentDate || new Date();
|
||||
const newDate = new Date(baseDate);
|
||||
|
||||
newDate.setHours(hours);
|
||||
newDate.setMinutes(minutes);
|
||||
newDate.setSeconds(0);
|
||||
newDate.setMilliseconds(0);
|
||||
|
||||
onChange(newDate.toISOString());
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<DatePicker
|
||||
size="md"
|
||||
value={formatDate(currentDate)}
|
||||
onChange={handleDateChange}
|
||||
{...rest}
|
||||
/>
|
||||
<TimeInput
|
||||
ref={timeRef}
|
||||
label="Time"
|
||||
size="md"
|
||||
value={formatTime(currentDate)}
|
||||
onChange={handleTimeChange}
|
||||
rightSection={
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
onClick={() => timeRef.current?.showPicker()}
|
||||
>
|
||||
<ClockIcon size={16} />
|
||||
</ActionIcon>
|
||||
}
|
||||
{...rest}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export { DateTimePicker };
|
||||
@@ -4,17 +4,17 @@ import { CaretRightIcon, Icon } from "@phosphor-icons/react";
|
||||
interface ListButtonProps {
|
||||
label: string;
|
||||
Icon: Icon;
|
||||
handleClick: () => void;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const ListButton = ({ label, handleClick, Icon }: ListButtonProps) => {
|
||||
const ListButton = ({ label, onClick, Icon }: ListButtonProps) => {
|
||||
return (
|
||||
<>
|
||||
<UnstyledButton
|
||||
w='100%'
|
||||
p='md'
|
||||
component={'button'}
|
||||
onClick={handleClick}
|
||||
onClick={onClick}
|
||||
>
|
||||
<Group>
|
||||
<Icon weight='bold' size={20} />
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Link, useNavigate } from "@tanstack/react-router";
|
||||
interface ListLinkProps {
|
||||
label: string;
|
||||
to: string;
|
||||
Icon: Icon;
|
||||
Icon?: Icon;
|
||||
}
|
||||
|
||||
const ListLink = ({ label, to, Icon }: ListLinkProps) => {
|
||||
@@ -19,7 +19,7 @@ const ListLink = ({ label, to, Icon }: ListLinkProps) => {
|
||||
component={'button'}
|
||||
onClick={() => navigate({ to })}
|
||||
label={<Text fw={500} size='md'>{label}</Text>}
|
||||
leftSection={<Icon weight='bold' size={20} />}
|
||||
leftSection={Icon && <Icon weight='bold' size={20} />}
|
||||
rightSection={<CaretRightIcon size={20} />}
|
||||
/>
|
||||
<Divider />
|
||||
|
||||
Reference in New Issue
Block a user