Deskripsi:

- New component: Datetime custom, datetime android, datetime ios
- Fix: event create input datetime

# No Issue
This commit is contained in:
2025-07-18 11:48:24 +08:00
parent eaf0ebfb0a
commit b8b1efc71e
4 changed files with 305 additions and 211 deletions

View File

@@ -1,40 +1,43 @@
/* eslint-disable import/no-duplicates */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
BoxButtonOnFooter,
ButtonCustom,
SelectCustom,
Spacing,
StackCustom,
TextAreaCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
BoxButtonOnFooter,
ButtonCustom,
SelectCustom,
StackCustom,
TextAreaCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import DateTimeInput from "@/components/DateInput/DateTimeIOS";
import DateTimePickerCustom from "@/components/DateInput/DateTimePickerCustom";
import { masterTypeEvent } from "@/lib/dummy-data/event/master-type-event";
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
import React, { useState } from "react";
import { Platform, StyleSheet } from "react-native";
import { Platform } from "react-native";
export default function EventCreate() {
const [selectedDateIOS, setSelectedDateIOS] = useState<DateTimePickerEvent>();
const [selectDateAndroid, setSelectDateAndroid] = useState<Date>(new Date());
const [selectedTimeAndroid, setSelectedTimeAndroid] = useState<Date>(
new Date()
);
const [selectedDate, setSelectedDate] = useState<
Date | DateTimePickerEvent | null
>(null);
const [selectedEndDate, setSelectedEndDate] = useState<
Date | DateTimePickerEvent | null
>(null);
const handlerSubmit = () => {
console.log("Simpan");
const combined = new Date(selectDateAndroid);
combined.setHours(selectedTimeAndroid.getHours());
combined.setMinutes(selectedTimeAndroid.getMinutes());
combined.setSeconds(selectedTimeAndroid.getSeconds());
combined.setMilliseconds(selectedTimeAndroid.getMilliseconds());
if (selectedDate) {
console.log("Tanggal yang dipilih:", selectedDate);
console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
// Kirim ke API atau proses lanjutan
} else {
console.warn("Tanggal belum dipilih");
}
const newDate = Platform.OS === "ios" ? selectedDateIOS : combined;
console.log(`newDate ${Platform.OS} > `, newDate);
if (selectedEndDate) {
console.log("Tanggal yang dipilih:", selectedEndDate);
console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
// Kirim ke API atau proses lanjutan
} else {
console.warn("Tanggal belum dipilih");
}
};
const buttonSubmit = (
@@ -43,39 +46,9 @@ export default function EventCreate() {
</BoxButtonOnFooter>
);
const time = () => {
return (
<>
{Platform.OS === "ios" ? (
<DateTimeInput
label="Tanggal Event"
value={selectedDateIOS}
onChange={(date: DateTimePickerEvent) => {
setSelectedDateIOS(date);
}}
required
/>
) : (
<DateTimePickerCustom
dateValue={selectDateAndroid}
timeValue={selectedTimeAndroid}
onChangeDate={(date: Date) => {
setSelectDateAndroid(date);
}}
onChangeTime={(time: Date) => {
setSelectedTimeAndroid(time);
}}
/>
)}
</>
);
};
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<TextCustom>Test Datetime</TextCustom>
<StackCustom gap={"xs"}>
<TextInputCustom
placeholder="Masukkan nama event"
@@ -94,7 +67,24 @@ export default function EventCreate() {
required
/>
{time()}
<DateTimePickerCustom
label="Tanggal & Waktu Mulai"
required
onChange={(date: Date) => {
setSelectedDate(date as any);
}}
value={selectedDate as any}
minimumDate={new Date(Date.now())}
/>
<DateTimePickerCustom
label="Tanggal & Waktu Berakhir"
required
onChange={(date: Date) => {
setSelectedEndDate(date as any);
}}
value={selectedEndDate as any}
/>
<TextAreaCustom
label="Deskripsi"
@@ -108,11 +98,3 @@ export default function EventCreate() {
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
// padding: 20,
},
});

View File

@@ -0,0 +1,205 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
// DateTimeInput.tsx
import { MainColor } from "@/constants/color-palet";
import { GStyles } from "@/styles/global-styles";
import { Ionicons } from "@expo/vector-icons";
import DateTimePicker, {
DateTimePickerEvent,
} from "@react-native-community/datetimepicker";
import React, { useCallback, useState } from "react";
import { Pressable, StyleProp, Text, View, ViewStyle } from "react-native";
import Grid from "../Grid/GridCustom";
import TextCustom from "../Text/TextCustom";
interface DateTimeInputProps {
// Main
value?: DateTimePickerEvent;
mode?: "date" | "time";
onChange: (selectedDate: DateTimePickerEvent) => void;
maximumDate?: Date;
minimumDate?: Date;
// Main
label?: string;
required?: boolean;
disabled?: boolean;
iconLeft?: React.ReactNode;
style?: StyleProp<ViewStyle>;
borderRadius?: number;
externalError?: string;
internalError?: string;
containerStyle?: StyleProp<ViewStyle>;
}
const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
// Main
value,
mode,
onChange,
maximumDate,
minimumDate,
// Main
label,
required,
disabled,
iconLeft,
style,
borderRadius = 8,
externalError,
internalError,
containerStyle,
}) => {
const [showDate, setShowDate] = useState(false);
const [showTime, setShowTime] = useState(false);
const [selectedDate, setSelectedDate] = useState<Date>(value as any);
const [selectedTime, setSelectedTime] = useState<Date>(value as any);
// Fungsi untuk menggabungkan tanggal dan waktu
const combineDateAndTime = useCallback((date: Date, time: Date): Date => {
const combined = new Date(date);
combined.setHours(
time.getHours(),
time.getMinutes(),
time.getSeconds(),
time.getMilliseconds()
);
return combined;
}, []);
// Handler untuk tanggal
const handleConfirmDate = (event: DateTimePickerEvent, date?: Date) => {
if (event.type === "set" && date) {
setSelectedDate(date);
if (selectedTime) {
const combined = combineDateAndTime(date, selectedTime);
onChange?.(combined as any);
}
}
setShowDate(false);
};
// Handler untuk waktu
const handleConfirmTime = (event: DateTimePickerEvent, time?: Date) => {
if (event.type === "set" && time) {
setSelectedTime(time);
if (selectedDate) {
const combined = combineDateAndTime(selectedDate, time);
onChange?.(combined as any);
}
}
setShowTime(false);
};
const toggleDatePicker = () => {
setShowDate(!showDate);
};
const toggleTimePicker = () => {
setShowTime(!showTime);
};
return (
<>
<View style={[GStyles.inputContainerArea, containerStyle]}>
{label && (
<Text style={GStyles.inputLabel}>
{label}
{required && <Text style={GStyles.inputRequired}> *</Text>}
</Text>
)}
<View
style={[
style,
{ borderRadius },
externalError || internalError ? GStyles.inputErrorBorder : null,
GStyles.inputContainerInput,
disabled && GStyles.disabledBox,
]}
>
<View style={GStyles.inputIcon}>
<Ionicons
name="calendar-outline"
size={20}
color={MainColor.placeholder}
/>
</View>
<Grid
containerStyle={{
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
}}
>
<Grid.Col span={6} style={{}}>
<Pressable onPress={toggleDatePicker}>
<TextCustom color="gray">
{selectedDate ? (
<TextCustom color="black">
{selectedDate.toLocaleDateString()}
</TextCustom>
) : (
"Pilih tanggal"
)}
</TextCustom>
</Pressable>
</Grid.Col>
<Grid.Col span={1} style={{ alignItems: "center" }}>
<TextCustom color="gray">|</TextCustom>
</Grid.Col>
<Grid.Col span={5} style={{}}>
<Pressable onPress={toggleTimePicker}>
<TextCustom color="gray">
{selectedTime ? (
<TextCustom color="black">
{selectedTime.toLocaleTimeString("id-ID", {
minute: "2-digit",
hour: "2-digit",
})}
</TextCustom>
) : (
"Pilih waktu"
)}
</TextCustom>
</Pressable>
</Grid.Col>
</Grid>
</View>
{externalError ||
(internalError && (
<Text style={GStyles.inputErrorMessage}>
{externalError || internalError}
</Text>
))}
</View>
{showDate && (
<DateTimePicker
testID="dateTimePicker"
value={selectedDate || new Date()}
mode="date"
is24Hour={true}
display="default"
onChange={handleConfirmDate}
minimumDate={minimumDate}
maximumDate={maximumDate}
/>
)}
{showTime && (
<DateTimePicker
testID="dateTimePicker"
value={selectedTime || new Date()}
mode="time"
is24Hour={true}
display="default"
onChange={handleConfirmTime}
minimumDate={minimumDate}
maximumDate={maximumDate}
/>
)}
</>
);
};
export default DateTimeInput_Android;

View File

@@ -1,35 +1,28 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
// DateTimeInput.tsx
import { MainColor } from "@/constants/color-palet";
import { GStyles } from "@/styles/global-styles";
import { Ionicons } from "@expo/vector-icons";
import DateTimePicker, {
DateTimePickerEvent,
DateTimePickerEvent,
} from "@react-native-community/datetimepicker";
import dayjs from "dayjs";
import React, { useState } from "react";
import {
Button,
Platform,
Text,
TouchableOpacity,
View,
StyleProp,
ViewStyle,
StyleProp,
Text,
View,
ViewStyle
} from "react-native";
import ButtonCustom from "../Button/ButtonCustom";
import TextCustom from "../Text/TextCustom";
import dayjs from "dayjs";
import TextInputCustom from "../TextInput/TextInputCustom";
import { GStyles } from "@/styles/global-styles";
import ButtonCenteredOnly from "../Button/ButtonCenteredOnly";
import Spacing from "../_ShareComponent/Spacing";
import Grid from "../Grid/GridCustom";
import { Ionicons } from "@expo/vector-icons";
import ClickableCustom from "../Clickable/ClickableCustom";
import { AccentColor, MainColor } from "@/constants/color-palet";
import TextCustom from "../Text/TextCustom";
interface DateTimeInputProps {
// Main
value?: DateTimePickerEvent;
mode?: "date" | "time";
onChange: (selectedDate: DateTimePickerEvent) => void;
maximumDate?: Date;
minimumDate?: Date;
// Main
label?: string;
required?: boolean;
@@ -42,11 +35,13 @@ interface DateTimeInputProps {
containerStyle?: StyleProp<ViewStyle>;
}
const DateTimeInput: React.FC<DateTimeInputProps> = ({
const DateTimeInput_IOS: React.FC<DateTimeInputProps> = ({
// Main
value,
mode,
onChange,
maximumDate,
minimumDate,
// Main
label,
required,
@@ -153,7 +148,8 @@ const DateTimeInput: React.FC<DateTimeInputProps> = ({
mode={"datetime"}
display="inline"
onChange={handleConfirm}
minimumDate={new Date(Date.now())} // 30 days from now
minimumDate={minimumDate}
maximumDate={maximumDate}
/>
</View>
</>
@@ -162,4 +158,4 @@ const DateTimeInput: React.FC<DateTimeInputProps> = ({
);
};
export default DateTimeInput;
export default DateTimeInput_IOS;

View File

@@ -1,143 +1,54 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { useState } from "react";
import { Pressable, Text, View, StyleSheet } from "react-native";
import DateTimePicker, {
import {
DateTimePickerEvent,
} from "@react-native-community/datetimepicker";
import { GStyles } from "@/styles/global-styles";
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
import { MainColor } from "@/constants/color-palet";
import Grid from "../Grid/GridCustom";
import TextCustom from "../Text/TextCustom";
import React from "react";
import { Platform } from "react-native";
import DateTimeInput_Android from "./DataTimeAndroid";
import DateTimeInput_IOS from "./DateTimeIOS";
type Props = {
dateValue?: Date;
timeValue?: Date;
onChangeDate: (date: Date) => void;
onChangeTime: (time: Date) => void;
value?: Date;
onChange?: (date: Date) => void;
label?: string;
required?: boolean;
maximumDate?: Date;
minimumDate?: Date;
};
const DateTimePickerCustom: React.FC<Props> = ({
dateValue,
timeValue,
onChangeDate,
onChangeTime,
value,
onChange,
label,
required,
maximumDate,
minimumDate,
}) => {
const [showDate, setShowDate] = useState(false);
const [showTime, setShowTime] = useState(false);
const toggleDatePicker = () => {
setShowDate(!showDate);
};
const toggleTimePicker = () => {
setShowTime(!showTime);
};
const handleConfirmDate = (
event: DateTimePickerEvent,
selectedDate?: Date
) => {
if (event.type === "set" && selectedDate !== undefined) {
onChangeDate(selectedDate);
}
setShowDate(false);
};
const handleConfirmTime = (
event: DateTimePickerEvent,
selectedTime?: Date
) => {
if (event.type === "set" && selectedTime !== undefined) {
onChangeTime(selectedTime);
}
setShowTime(false);
};
return (
<>
{/* <Pressable onPress={toggleDatePicker} style={[GStyles.inputContainerInput, {borderRadius: 8} ]}>
<Text style={styles.buttonText}>
{value ? value.toLocaleDateString() : "Pilih tanggal"}
</Text>
</Pressable> */}
<View
style={{
paddingBlock: 6,
paddingInline: 12,
borderRadius: 8,
backgroundColor: MainColor.white,
}}
>
<Grid
containerStyle={{
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
{Platform.OS === "ios" ? (
<DateTimeInput_IOS
label={label}
onChange={(date: DateTimePickerEvent) => {
onChange?.(date as any);
}}
>
<Grid.Col span={6} style={{}}>
<Pressable onPress={toggleDatePicker}>
<Text style={styles.buttonText}>
{dateValue ? dateValue.toLocaleDateString() : "Pilih tanggal"}
</Text>
</Pressable>
</Grid.Col>
<Grid.Col span={1} style={{ alignItems: "center" }}>
<TextCustom>|</TextCustom>
</Grid.Col>
<Grid.Col span={5} style={{}}>
<Pressable onPress={toggleTimePicker}>
<Text style={styles.buttonText}>
{timeValue ? timeValue.toLocaleTimeString("id-ID", { minute: "2-digit", hour: "2-digit" }) : "Pilih waktu"}
</Text>
</Pressable>
</Grid.Col>
</Grid>
</View>
{showDate && (
<DateTimePicker
testID="dateTimePicker"
value={dateValue || new Date()}
mode="date"
is24Hour={true}
display="default"
onChange={handleConfirmDate}
required={required}
maximumDate={maximumDate}
minimumDate={minimumDate}
/>
)}
{showTime && (
<DateTimePicker
testID="dateTimePicker"
value={timeValue || new Date()}
mode="time"
is24Hour={true}
display="default"
onChange={handleConfirmTime}
) : (
<DateTimeInput_Android
label={label}
onChange={(date: DateTimePickerEvent) => {
onChange?.(date as any);
}}
required={required}
maximumDate={maximumDate}
minimumDate={minimumDate}
/>
)}
</>
);
};
const styles = StyleSheet.create({
button: {
paddingVertical: 12,
paddingHorizontal: 20,
backgroundColor: "#007AFF",
borderRadius: 8,
alignItems: "center",
justifyContent: "center",
marginVertical: 10,
},
buttonText: {
color: MainColor.black,
fontSize: TEXT_SIZE_MEDIUM,
// fontWeight: "bold",
},
});
export default DateTimePickerCustom;