20260507213409
This commit is contained in:
1 parent
3070eac71b
commit
4c7f516a03
204 files changed
+3623
No files matched your search
@@ -0,0 +1,103 @@
|
||||
import { DatePicker as YzDatePicker } from "@yz1311/react-native-wheel-picker";
|
||||
import dayjs from "dayjs";
|
||||
import { BottomSheet, Button, Spinner } from "heroui-native";
|
||||
import { useState, useEffect } from "react";
|
||||
import { toDate } from "@/utils/time";
|
||||
import { View } from "react-native";
|
||||
import { CheckIcon } from "lucide-react-native";
|
||||
import { FadeIn } from "react-native-reanimated";
|
||||
|
||||
export type DatePickerMode = "year" | "month" | "date" | "time" | "datetime";
|
||||
|
||||
export type DateFormatType = "YYYY" | "YYYY-MM" | "YYYY-MM-DD" | "HH:mm:ss" | "YYYY-MM-DD HH:mm";
|
||||
|
||||
interface DatePickerProps {
|
||||
value: Date | string;
|
||||
show?: boolean;
|
||||
onClose?: () => void;
|
||||
onConfirm?: (value: string) => void | Promise<void>;
|
||||
mode?: DatePickerMode;
|
||||
format?: DateFormatType;
|
||||
}
|
||||
|
||||
const defaultFormatMap: Record<DatePickerMode, DateFormatType> = {
|
||||
year: "YYYY",
|
||||
month: "YYYY-MM",
|
||||
date: "YYYY-MM-DD",
|
||||
time: "HH:mm:ss",
|
||||
datetime: "YYYY-MM-DD HH:mm",
|
||||
};
|
||||
|
||||
export default function DateTime({
|
||||
value,
|
||||
show = false,
|
||||
onClose,
|
||||
onConfirm,
|
||||
mode = "date",
|
||||
format,
|
||||
}: DatePickerProps) {
|
||||
const finalFormat = format ?? defaultFormatMap[mode];
|
||||
|
||||
const [tempDate, setTempDate] = useState<Date>(toDate(value) ?? new Date());
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
setTempDate(toDate(value) ?? new Date());
|
||||
}
|
||||
}, [show, value]);
|
||||
|
||||
const handleClose = () => {
|
||||
if (loading) return;
|
||||
onClose?.();
|
||||
};
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!tempDate || loading) return;
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
const result = dayjs(tempDate).format(finalFormat);
|
||||
|
||||
await onConfirm?.(result);
|
||||
|
||||
handleClose();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<BottomSheet isOpen={show} onOpenChange={(v) => !v && handleClose()}>
|
||||
<BottomSheet.Portal>
|
||||
<BottomSheet.Overlay />
|
||||
|
||||
<BottomSheet.Content>
|
||||
<View style={{ width: "100%", alignItems: "center" }}>
|
||||
<YzDatePicker
|
||||
showHeader={false}
|
||||
date={tempDate}
|
||||
mode={mode}
|
||||
isModal={false}
|
||||
onDateChange={(d: Date) => setTempDate(d)}
|
||||
/>
|
||||
|
||||
<Button className="w-full" onPress={handleConfirm} isDisabled={loading}>
|
||||
{loading ? (
|
||||
<Spinner entering={FadeIn.delay(50)} color="white" />
|
||||
) : (
|
||||
<>
|
||||
<CheckIcon color="#fff" />
|
||||
<Button.Label>确认</Button.Label>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</View>
|
||||
</BottomSheet.Content>
|
||||
</BottomSheet.Portal>
|
||||
</BottomSheet>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user