import React, { JSX, useState } from "react"; import { View, Text, TextInput, TouchableOpacity, Image, StyleSheet, GestureResponderEvent, ScrollView, KeyboardAvoidingView, Platform, } from "react-native"; import { Dropdown } from "react-native-element-dropdown"; import { DateTimePickerAndroid } from "@react-native-community/datetimepicker"; import * as ImagePicker from "expo-image-picker"; import { Formik, FormikHelpers } from "formik"; import * as Yup from "yup"; import ChevronRight from "../../assets/icons/chevron_rightside.svg"; import AddPhoto from "../../assets/icons/add_photo_alternate.svg"; import IssueSelectorModal from "@/components/service/IssueSelectorModal"; import { uploadImage } from "@/utils/User"; import api from "@/services/axiosClient"; import { useSnackbar } from "@/contexts/Snackbar"; import { BASE_URL } from "@/constants/config"; import { Overlay } from "@/components/common/Overlay"; import CrossIcon from "@/assets/icons/close_white.svg"; import { useTranslation } from "react-i18next"; import CalendarIcon from "@/assets/icons/calendar.svg"; interface FormValues { serviceType: string | null; issues: string[]; comments: string | null; date: Date | null; photos: string[]; } const validationSchema = Yup.object().shape({ serviceType: Yup.string().required("Service Type is required"), issues: Yup.array().min(1, "At least one issue is required"), date: Yup.date().required("Date and Time is required"), photos: Yup.array().min(1, "At least one photo is required"), comments: Yup.string(), }); export default function ServiceFormScreen(): JSX.Element { const [isFocus, setIsFocus] = useState(false); const [isIssueSelectorVisible, setIssueSelectorVisible] = useState(false); const { showSnackbar } = useSnackbar(); function toggleIssueSelector() { setIssueSelectorVisible(!isIssueSelectorVisible); } const initialValues: FormValues = { serviceType: null, issues: [], comments: "", date: null, photos: [], }; const handlePhotoPick = async ( setFieldValue: (field: string, value: any) => void, currentPhotos: string[] ) => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, quality: 0.5, allowsMultipleSelection: true, }); if (!result.canceled) { const newPhotos = result.assets.map((asset) => asset.uri); const allPhotos = [...currentPhotos, ...newPhotos]; setFieldValue("photos", allPhotos); } }; const showPicker = ( currentDate: Date | null, setFieldValue: (field: string, value: any) => void ) => { const now = currentDate || new Date(); // First, show the date picker DateTimePickerAndroid.open({ value: now, mode: "date", is24Hour: false, display: "default", minimumDate: now, onChange: (event, selectedDate) => { if (event.type === "set" && selectedDate) { // When date is selected, show time picker next DateTimePickerAndroid.open({ value: selectedDate, mode: "time", is24Hour: false, display: "default", onChange: (timeEvent, selectedTime) => { if (timeEvent.type === "set" && selectedTime) { // Combine date and time into one Date object const combinedDate = new Date( selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate(), selectedTime.getHours(), selectedTime.getMinutes() ); if (combinedDate < now) { showSnackbar(`${t("service.select-valid-time")}`, "error"); return; } setFieldValue("date", combinedDate); } }, }); } }, }); }; const { t } = useTranslation(); return ( ) => { try { const uploadedPhotoUrls: string[] = []; for (const uri of values.photos) { const uploadedUrl = await uploadImage(uri); uploadedPhotoUrls.push(uploadedUrl); } console.log("IMAGES UPLOADED"); const payload = { service_type: values.serviceType, issue_types: values.issues, scheduled_time: values.date?.toISOString(), photos: uploadedPhotoUrls, comments: values.comments, }; const response = await api.post( `${BASE_URL}/api/v1/schedule-maintenance`, payload ); if (!response.data.success) { console.log(response.data?.message || "Submission failed"); throw new Error(response.data?.message || "Submission failed"); } console.log("Submission successful:", response.data); showSnackbar( `${t("service.service-request-success")}`, "success" ); actions.resetForm(); } catch (error: any) { console.error("Error during submission:", error); showSnackbar(`${t("service.something-went-wrong")}`, "error"); } finally { actions.setSubmitting(false); } }} > {({ handleChange, handleBlur, handleSubmit, values, setFieldValue, errors, touched, isSubmitting, }) => ( {t("service.service-type")}{" "} * setIsFocus(true)} onBlur={() => setIsFocus(false)} onChange={(item) => { setFieldValue("serviceType", item.value); setIsFocus(false); }} renderLeftIcon={() => ( {/* Add your icon component here if needed */} )} /> {touched.serviceType && errors.serviceType && ( {errors.serviceType} )} {t("service.issue")} * {values.issues.length > 0 ? values.issues.length + " issues selected" : `${t("service.select-issue")}`} {touched.issues && errors.issues && ( {errors.issues} )} {t("service.select-datetime")}{" "} * showPicker(values.date, setFieldValue)} style={styles.inputBoxDate} > {values.date ? values.date.toLocaleString() : `${t("service.select")}`} {touched.date && errors.date && ( {`${errors.date}`} )} handlePhotoPick(setFieldValue, values.photos)} > {t("service.add-photos")}{" "} {t("service.supported-formats")} {/* Selected Images Preview */} {values.photos.map((uri, index) => ( { const updatedPhotos = [...values.photos]; updatedPhotos.splice(index, 1); setFieldValue("photos", updatedPhotos); }} > ))} {touched.photos && errors.photos && ( {errors.photos} )} {t("service.comments")} {values.comments?.length || 0}/100 {t("service.words")} void} > {t("service.submit")} { setFieldValue("issues", selectedIssues); }} initialSelectedValues={values.issues} /> {isSubmitting && } )} ); } const styles = StyleSheet.create({ container: { flex: 1, }, inputContainer: {}, screen: { flex: 1, backgroundColor: "#F3F5F8", }, scrollContent: { paddingBottom: 116, }, topBar: { height: 56, backgroundColor: "#F3F5F8", justifyContent: "center", paddingHorizontal: 16, }, topBarText: { fontSize: 16, fontWeight: "600", color: "#252A34", }, formContainer: { paddingHorizontal: 16, }, label: { fontSize: 14, fontWeight: "500", color: "#252A34", marginBottom: 4, }, required: { color: "#D42210", }, inputBox: { backgroundColor: "#FFFFFF", borderColor: "#D8DDE7", borderRadius: 4, paddingHorizontal: 8, height: 40, marginTop: 8, flexDirection: "row", alignItems: "center", justifyContent: "space-between", }, inputBoxDate: { backgroundColor: "#FFFFFF", borderColor: "#D8DDE7", borderWidth: 1, borderRadius: 4, paddingHorizontal: 8, height: 40, flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 4, }, picker: { height: 40, width: "100%", }, issueText: { color: "#006C4D", }, dateText: { color: "#949CAC", }, photoBox: { backgroundColor: "#FFFFFF", borderColor: "#949CAC", borderWidth: 1, borderRadius: 4, height: 64, justifyContent: "center", alignItems: "center", marginBottom: 8, borderStyle: "dashed", marginTop: 8, }, addPhotoText: { fontSize: 14, color: "#252A34", fontWeight: "500", }, helperText: { fontSize: 12, color: "#717B8F", marginBottom: 8, }, commentInput: { backgroundColor: "#FFFFFF", borderColor: "#D8DDE7", borderWidth: 1, borderRadius: 4, padding: 10, height: 80, textAlignVertical: "top", marginTop: 8, }, wordCount: { textAlign: "right", color: "#717B8F", fontSize: 14, marginTop: 4, }, submitButton: { marginTop: 24, backgroundColor: "#00875F", borderRadius: 4, height: 48, justifyContent: "center", alignItems: "center", }, submitText: { color: "#FCFCFC", fontSize: 14, fontWeight: "500", }, photo: { width: 80, height: 80, resizeMode: "cover", }, error: { color: "#D42210", fontSize: 12, marginBottom: 8, }, photosContainer: { flexDirection: "row", flexWrap: "wrap", marginTop: 8, gap: 8, }, photoPreviewContainer: { position: "relative", }, photoPreview: { width: 80, height: 80, borderRadius: 4, }, removePhotoButton: { position: "absolute", top: 4, right: 4, backgroundColor: "#252A345C", borderRadius: 12, width: 24, height: 24, justifyContent: "center", alignItems: "center", }, removePhotoText: { color: "white", fontSize: 18, fontWeight: "bold", lineHeight: 20, }, dropdown: { height: 40, borderColor: "#D8DDE7", borderWidth: 1, borderRadius: 4, paddingHorizontal: 8, backgroundColor: "#FFFFFF", marginTop: 8, }, placeholderStyle: { fontSize: 14, color: "#252A34", }, selectedTextStyle: { fontSize: 14, color: "#252A34", }, iconStyle: { width: 20, height: 20, }, inputSearchStyle: { height: 40, fontSize: 16, }, dropdownMenu: { backgroundColor: "#FCFCFC", borderRadius: 4, shadowColor: "#0E1118", shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.1, shadowRadius: 32, elevation: 4, }, dropdownItem: { padding: 16, height: 36, flexDirection: "row", justifyContent: "space-between", alignItems: "center", }, dropdownItemText: { fontSize: 14, color: "#252A34", }, });