Initial commit
This commit is contained in:
263
src/components/CustomBottomSheet/DatePickerBottomSheet.tsx
Normal file
263
src/components/CustomBottomSheet/DatePickerBottomSheet.tsx
Normal file
@@ -0,0 +1,263 @@
|
||||
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 years = Array.from({ length: 21 }, (_, i) => {
|
||||
const year = new Date().getFullYear() - 10 + 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")}
|
||||
snapPoints={["55vh"]}
|
||||
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: "#ffffff",
|
||||
overflow: "hidden",
|
||||
width: "100%",
|
||||
height: 250,
|
||||
}}
|
||||
aria-selected={false}
|
||||
>
|
||||
<Picker.Column
|
||||
name="month"
|
||||
style={{
|
||||
flex: 1,
|
||||
borderRight: "1px solid #e5e7eb",
|
||||
backgroundColor: "#ffffff",
|
||||
}}
|
||||
>
|
||||
{pickerOptions.month.map((option) => (
|
||||
<Picker.Item key={option.value} value={option.value}>
|
||||
{({ selected }) => (
|
||||
<div
|
||||
style={{
|
||||
fontWeight: selected ? "600" : "400",
|
||||
color: selected ? "#171717" : "#9ca3af",
|
||||
fontSize: "16px",
|
||||
padding: "9px 0",
|
||||
textAlign: "center",
|
||||
opacity: selected ? 1 : 0.6,
|
||||
transition: "all 0.2s ease",
|
||||
lineHeight: "1.2",
|
||||
height: 36,
|
||||
width: "100%",
|
||||
backgroundColor: selected ? "#f3f4f6" : "transparent",
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
)}
|
||||
</Picker.Item>
|
||||
))}
|
||||
</Picker.Column>
|
||||
<Picker.Column
|
||||
name="day"
|
||||
style={{
|
||||
flex: 1,
|
||||
borderRight: "1px solid #e5e7eb",
|
||||
backgroundColor: "#ffffff",
|
||||
}}
|
||||
>
|
||||
{pickerOptions.day.map((option) => (
|
||||
<Picker.Item key={option.value} value={option.value}>
|
||||
{({ selected }) => (
|
||||
<div
|
||||
style={{
|
||||
fontWeight: selected ? "600" : "400",
|
||||
color: selected ? "#171717" : "#9ca3af",
|
||||
fontSize: "16px",
|
||||
padding: "9px 0",
|
||||
textAlign: "center",
|
||||
opacity: selected ? 1 : 0.6,
|
||||
transition: "all 0.2s ease",
|
||||
lineHeight: "1.2",
|
||||
height: 36,
|
||||
width: "100%",
|
||||
backgroundColor: selected ? "#f3f4f6" : "transparent",
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
)}
|
||||
</Picker.Item>
|
||||
))}
|
||||
</Picker.Column>
|
||||
<Picker.Column
|
||||
name="year"
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: "#ffffff",
|
||||
}}
|
||||
>
|
||||
{pickerOptions.year.map((option) => (
|
||||
<Picker.Item key={option.value} value={option.value}>
|
||||
{({ selected }) => (
|
||||
<div
|
||||
style={{
|
||||
fontWeight: selected ? "600" : "400",
|
||||
color: selected ? "#171717" : "#9ca3af",
|
||||
fontSize: "16px",
|
||||
padding: "9px 0",
|
||||
textAlign: "center",
|
||||
opacity: selected ? 1 : 0.6,
|
||||
transition: "all 0.2s ease",
|
||||
lineHeight: "1.2",
|
||||
height: 36,
|
||||
width: "100%",
|
||||
backgroundColor: selected ? "#f3f4f6" : "transparent",
|
||||
}}
|
||||
>
|
||||
{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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user