Fix Component Datetime IOS

Components
- components/DateInput/DataTimeAndroid.tsx
- components/DateInput/DateTimeIOS.tsx
- components/Notification/NotificationInitializer.tsx

Screens
- screens/Event/ScreenStatus.tsx

Docs
- docs/prompt-for-qwen-code.md

### No Issue
This commit is contained in:
2026-02-04 12:00:00 +08:00
parent 771ae45f26
commit 60177a1087
5 changed files with 132 additions and 61 deletions

View File

@@ -1,4 +1,3 @@
// DateTimeInput.tsx // DateTimeInput.tsx
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
@@ -7,7 +6,14 @@ import DateTimePicker, {
DateTimePickerEvent, DateTimePickerEvent,
} from "@react-native-community/datetimepicker"; } from "@react-native-community/datetimepicker";
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import { Pressable, StyleProp, Text, View, ViewStyle } from "react-native"; import {
Keyboard,
Pressable,
StyleProp,
Text,
View,
ViewStyle,
} from "react-native";
import Grid from "../Grid/GridCustom"; import Grid from "../Grid/GridCustom";
import TextCustom from "../Text/TextCustom"; import TextCustom from "../Text/TextCustom";
@@ -53,7 +59,7 @@ const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
const [selectedDate, setSelectedDate] = useState<Date>(value as any); const [selectedDate, setSelectedDate] = useState<Date>(value as any);
const [selectedTime, setSelectedTime] = useState<Date>(value as any); const [selectedTime, setSelectedTime] = useState<Date>(value as any);
console.log("Date Android", value) console.log("Date Android", value);
// Fungsi untuk menggabungkan tanggal dan waktu // Fungsi untuk menggabungkan tanggal dan waktu
const combineDateAndTime = useCallback((date: Date, time: Date): Date => { const combineDateAndTime = useCallback((date: Date, time: Date): Date => {
@@ -62,7 +68,7 @@ const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
time.getHours(), time.getHours(),
time.getMinutes(), time.getMinutes(),
time.getSeconds(), time.getSeconds(),
time.getMilliseconds() time.getMilliseconds(),
); );
return combined; return combined;
}, []); }, []);
@@ -92,10 +98,12 @@ const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
}; };
const toggleDatePicker = () => { const toggleDatePicker = () => {
Keyboard.dismiss();
setShowDate(!showDate); setShowDate(!showDate);
}; };
const toggleTimePicker = () => { const toggleTimePicker = () => {
Keyboard.dismiss();
setShowTime(!showTime); setShowTime(!showTime);
}; };

View File

@@ -1,13 +1,22 @@
// DateTimeInput.tsx // DateTimeInput.tsx
import { MainColor } from "@/constants/color-palet"; import { AccentColor, MainColor } from "@/constants/color-palet";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import DateTimePicker, { import DateTimePicker, {
DateTimePickerEvent, DateTimePickerEvent,
} from "@react-native-community/datetimepicker"; } from "@react-native-community/datetimepicker";
import dayjs from "dayjs"; import dayjs from "dayjs";
import React, { useState } from "react"; import React, { useState, useRef } from "react";
import { Button, StyleProp, Text, View, ViewStyle } from "react-native"; import {
Button,
StyleProp,
Text,
View,
ViewStyle,
Keyboard,
TouchableOpacity,
Modal,
} from "react-native";
import ClickableCustom from "../Clickable/ClickableCustom"; import ClickableCustom from "../Clickable/ClickableCustom";
import TextCustom from "../Text/TextCustom"; import TextCustom from "../Text/TextCustom";
@@ -50,20 +59,35 @@ const DateTimeInput_IOS: React.FC<DateTimeInputProps> = ({
}) => { }) => {
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const [selectedDate, setSelectedDate] = useState<Date | undefined>( const [selectedDate, setSelectedDate] = useState<Date | undefined>(
value as any value as any,
);
// State sementara untuk menyimpan nilai yang dipilih
const [tempSelectedDate, setTempSelectedDate] = useState<Date | undefined>(
value as any,
); );
const handleConfirm = (event: any, date?: Date) => { const handleConfirm = (event: any, date?: Date) => {
if (event.type === "set" && date !== undefined) { if (event.type === "set" && date !== undefined) {
setSelectedDate(date); // Hanya perbarui state sementara, bukan state utama
onChange(date as any); setTempSelectedDate(date);
} }
}; };
const handlePress = () => { const handlePress = () => {
// Sembunyikan keyboard sebelum menampilkan date picker
Keyboard.dismiss();
// Set state sementara ke nilai saat ini
setTempSelectedDate(selectedDate);
setShow(!show); setShow(!show);
}; };
// Fungsi untuk menangani klik di luar area picker
const handleOutsidePress = () => {
if (show) {
setShow(false);
}
};
return ( return (
<> <>
<ClickableCustom <ClickableCustom
@@ -112,84 +136,125 @@ const DateTimeInput_IOS: React.FC<DateTimeInputProps> = ({
))} ))}
</ClickableCustom> </ClickableCustom>
{show && ( <Modal
<> animationType="fade"
<View transparent={true}
visible={show}
onRequestClose={() => setShow(false)}
>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0, 0, 0, 0.5)", // Efek blur dengan background semi-transparan
}}
>
<TouchableOpacity
style={{ style={{
position: "absolute", position: "absolute",
zIndex: 15, top: 0,
backgroundColor: "white",
borderRadius: 8,
padding: 10,
// top: 0,
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
borderColor: "#ccc", }}
activeOpacity={1}
onPress={handleOutsidePress}
>
<View style={{ flex: 1 }} />
</TouchableOpacity>
<View
style={{
zIndex: 15,
backgroundColor: MainColor.white_gray,
borderRadius: 16,
padding: 20,
marginHorizontal: 20,
width: "95%",
maxWidth: 400,
borderColor: MainColor.placeholder,
borderWidth: 1, borderWidth: 1,
}} }}
onStartShouldSetResponder={() => true} // Mencegah event bubbling ke TouchableOpacity induk
onResponderRelease={() => {}} // Handler kosong untuk mencegah event bubbling
> >
{/* <View style={{ alignItems: "flex-start" }}> {/* <View
<Ionicons style={{
name="close" flexDirection: "row",
size={20} justifyContent: "space-between",
color="black" alignItems: "center",
onPress={() => { marginBottom: 10,
setShow(false); }}
setSelectedDate(undefined); >
<Text
style={{
fontSize: 18,
fontWeight: "bold",
color: MainColor.black,
}} }}
/> >
Pilih Tanggal & Waktu
</Text>
<TouchableOpacity onPress={() => setShow(false)}>
<Ionicons
name="close"
size={24}
color={AccentColor.blackgray}
/>
</TouchableOpacity>
</View> */} </View> */}
<DateTimePicker <DateTimePicker
value={selectedDate || new Date()} value={tempSelectedDate || new Date()}
mode={"datetime"} mode={"datetime"}
display="spinner" display="inline"
onChange={handleConfirm} onChange={handleConfirm}
minimumDate={minimumDate} minimumDate={minimumDate}
maximumDate={maximumDate} maximumDate={maximumDate}
themeVariant="light" themeVariant="light"
/> />
<View style={{ flexDirection: "row", gap: 10 }}> <View style={{ flexDirection: "row", gap: 10, marginTop: 15 }}>
<ClickableCustom <TouchableOpacity
onPress={() => { onPress={() => {
setShow(false) setShow(false);
setSelectedDate(undefined) // Kembalikan ke nilai sebelumnya jika batal
setTempSelectedDate(selectedDate);
}} }}
style={{ style={{
flex: 1,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
padding: 12, padding: 12,
borderRadius: 10, borderRadius: 10,
backgroundColor: MainColor.placeholder, backgroundColor: MainColor.placeholder,
marginTop: 10,
width: "48%",
}} }}
> >
<TextCustom color="black">Batal</TextCustom> <TextCustom color="black">Batal</TextCustom>
</ClickableCustom> </TouchableOpacity>
<ClickableCustom <TouchableOpacity
onPress={() => { onPress={() => {
setShow(false) // Simpan nilai yang dipilih ke state utama hanya saat OK ditekan
onChange(selectedDate as any) setSelectedDate(tempSelectedDate);
onChange(tempSelectedDate as any);
setShow(false);
}} }}
style={{ style={{
flex: 1,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
padding: 12, padding: 12,
borderRadius: 10, borderRadius: 10,
backgroundColor: MainColor.darkblue, backgroundColor: MainColor.darkblue,
marginTop: 10,
width: "48%",
}} }}
> >
<TextCustom>OK</TextCustom> <TextCustom>OK</TextCustom>
</ClickableCustom> </TouchableOpacity>
</View> </View>
</View> </View>
</> </View>
)} </Modal>
</> </>
); );
}; };

View File

@@ -51,7 +51,6 @@ export default function NotificationInitializer() {
if (!fcmToken) { if (!fcmToken) {
console.warn("Tidak bisa mendapatkan FCM token"); console.warn("Tidak bisa mendapatkan FCM token");
// logout(); // logout();
return;
} }
console.log("✅ FCM Token:", fcmToken); console.log("✅ FCM Token:", fcmToken);

View File

@@ -22,4 +22,5 @@ Gunakan bahasa indonesia pada cli agar saya mudah membacanya.
<!-- Start Penerapan NewWrapper --> <!-- Start Penerapan NewWrapper -->
Terapkan NewWrapper pada file: screens/Forum/DetailForum.tsx Terapkan NewWrapper pada file: screens/Forum/DetailForum.tsx
Component yang digunakan: components/_ShareComponent/NewWrapper.tsx , karena ini adalah halaman detail saya ingin anda fokus pada props pada NewWrapper. Seperti Component yang digunakan: components/_ShareComponent/NewWrapper.tsx , karena ini adalah halaman detail saya ingin anda fokus pada props pada NewWrapper. Seperti
<!-- -->

View File

@@ -26,7 +26,7 @@ export default function Event_ScreenStatus() {
const id = user?.id || ""; const id = user?.id || "";
const [activeCategory, setActiveCategory] = useState<string | null>( const [activeCategory, setActiveCategory] = useState<string | null>(
status || "publish" status || "publish",
); );
// Setup pagination // Setup pagination
@@ -46,14 +46,15 @@ export default function Event_ScreenStatus() {
}); });
// Generate komponen // Generate komponen
const { ListEmptyComponent, ListFooterComponent } = createPaginationComponents({ const { ListEmptyComponent, ListFooterComponent } =
loading: pagination.loading, createPaginationComponents({
refreshing: pagination.refreshing, loading: pagination.loading,
listData: pagination.listData, refreshing: pagination.refreshing,
emptyMessage: `Tidak ada data ${activeCategory}`, listData: pagination.listData,
skeletonCount: 5, emptyMessage: `Tidak ada data ${activeCategory}`,
skeletonHeight: 100, skeletonCount: 5,
}); skeletonHeight: 100,
});
// Render item event // Render item event
const renderEventItem = ({ item }: { item: any }) => ( const renderEventItem = ({ item }: { item: any }) => (
@@ -100,11 +101,8 @@ export default function Event_ScreenStatus() {
return ( return (
<NewWrapper <NewWrapper
headerComponent={ hideFooter
<View style={{ paddingTop: 8 }}> headerComponent={<View style={{ paddingTop: 8 }}>{tabsComponent}</View>}
{tabsComponent}
</View>
}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderEventItem} renderItem={renderEventItem}
refreshControl={ refreshControl={