Files
web-menu-react-version-/src/components/CustomBottomSheet/DatePickerBottomSheet.tsx

289 lines
8.9 KiB
TypeScript

import { Button } from "antd";
import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet";
import Picker from "../WheelPicker";
interface DatePickerBottomSheetProps {
isOpen: boolean;
onClose: () => void;
onDateSelect?: (date: { month: string; day: string; year: string }) => void;
initialDate?: Date;
}
export default function DatePickerBottomSheet({
isOpen,
onClose,
onDateSelect,
initialDate = new Date(),
}: DatePickerBottomSheetProps) {
const { t } = useTranslation();
const [selectedDate, setSelectedDate] = useState({
month: (initialDate.getMonth() + 1).toString().padStart(2, "0"),
day: initialDate.getDate().toString().padStart(2, "0"),
year: initialDate.getFullYear().toString(),
});
// Generate picker options
const pickerOptions = useMemo(() => {
const months = [
{ value: "01", label: t("common.January") },
{ value: "02", label: t("common.February") },
{ value: "03", label: t("common.March") },
{ value: "04", label: t("common.April") },
{ value: "05", label: t("common.May") },
{ value: "06", label: t("common.June") },
{ value: "07", label: t("common.July") },
{ value: "08", label: t("common.August") },
{ value: "09", label: t("common.September") },
{ value: "10", label: t("common.October") },
{ value: "11", label: t("common.November") },
{ value: "12", label: t("common.December") },
];
const days = Array.from({ length: 31 }, (_, i) => ({
value: (i + 1).toString().padStart(2, "0"),
label: (i + 1).toString(),
}));
const currentYear = new Date().getFullYear();
const years = Array.from(
{ length: currentYear - 10 - 1900 + 1 },
(_, i) => {
const year = 1900 + i;
return {
value: year.toString(),
label: year.toString(),
};
},
);
return {
month: months,
day: days,
year: years,
};
}, [t]);
const handleDateChange = (month: string, day: string, year: string) => {
setSelectedDate((prev) => ({
...prev,
month,
day,
year,
}));
};
const handleConfirm = () => {
onDateSelect?.(selectedDate);
onClose();
};
const handleTouchStart = (e: React.TouchEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleTouchMove = (e: React.TouchEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleTouchEnd = (e: React.TouchEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};
const handleWheel = (e: React.WheelEvent<HTMLDivElement>) => {
e.stopPropagation();
};
return (
<ProBottomSheet
isOpen={isOpen}
onClose={onClose}
title={t("common.pickYourBirthday")}
height={600}
snapPoints={[460]}
showCloseButton={true}
>
<div
style={{
display: "flex",
flexDirection: "column",
}}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onWheel={handleWheel}
>
{/* Date Picker */}
<div
style={{
flex: 1,
display: "flex",
justifyContent: "center",
alignItems: "center",
position: "relative",
}}
>
<Picker
value={selectedDate}
onChange={(value) => {
handleDateChange(value.month, value.day, value.year);
}}
width="100%"
height={250}
style={{
position: "relative",
display: "flex",
backgroundColor: "var(--secondary-background)",
overflow: "hidden",
width: "100%",
height: 250,
border: "1px solid var(--border)",
borderRadius: "8px",
}}
aria-selected={false}
>
<Picker.Column
name="month"
style={{
flex: 1,
borderRight: "1px solid var(--border)",
backgroundColor: "var(--secondary-background)",
}}
>
{pickerOptions.month.map((option) => (
<Picker.Item key={option.value} value={option.value}>
{({ selected }) => (
<div
style={{
fontWeight: selected ? "600" : "400",
color: selected
? "var(--foreground)"
: "var(--text-color-gray)",
fontSize: "16px",
padding: "9px 0",
textAlign: "center",
opacity: selected ? 1 : 0.7,
transition: "all 0.2s ease",
lineHeight: "1.2",
height: 36,
width: "100%",
backgroundColor: selected
? "var(--background)"
: "transparent",
borderRadius: selected ? "4px" : "0",
margin: selected ? "2px 4px" : "0",
}}
>
{option.label}
</div>
)}
</Picker.Item>
))}
</Picker.Column>
<Picker.Column
name="day"
style={{
flex: 1,
borderRight: "1px solid var(--border)",
backgroundColor: "var(--secondary-background)",
}}
>
{pickerOptions.day.map((option) => (
<Picker.Item key={option.value} value={option.value}>
{({ selected }) => (
<div
style={{
fontWeight: selected ? "600" : "400",
color: selected
? "var(--foreground)"
: "var(--text-color-gray)",
fontSize: "16px",
padding: "9px 0",
textAlign: "center",
opacity: selected ? 1 : 0.7,
transition: "all 0.2s ease",
lineHeight: "1.2",
height: 36,
width: "100%",
backgroundColor: selected
? "var(--background)"
: "transparent",
borderRadius: selected ? "4px" : "0",
margin: selected ? "2px 4px" : "0",
}}
>
{option.label}
</div>
)}
</Picker.Item>
))}
</Picker.Column>
<Picker.Column
name="year"
style={{
flex: 1,
backgroundColor: "var(--secondary-background)",
}}
>
{pickerOptions.year.map((option) => (
<Picker.Item key={option.value} value={option.value}>
{({ selected }) => (
<div
style={{
fontWeight: selected ? "600" : "400",
color: selected
? "var(--foreground)"
: "var(--text-color-gray)",
fontSize: "16px",
padding: "9px 0",
textAlign: "center",
opacity: selected ? 1 : 0.7,
transition: "all 0.2s ease",
lineHeight: "1.2",
height: 36,
width: "100%",
backgroundColor: selected
? "var(--background)"
: "transparent",
borderRadius: selected ? "4px" : "0",
margin: selected ? "2px 4px" : "0",
}}
>
{option.label}
</div>
)}
</Picker.Item>
))}
</Picker.Column>
</Picker>
</div>
<Button
type="primary"
style={{ width: "100%", height: 50, marginTop: 10 }}
onClick={handleConfirm}
>
{t("common.confirm")}
</Button>
</div>
</ProBottomSheet>
);
}