289 lines
8.9 KiB
TypeScript
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>
|
|
);
|
|
}
|