Complete service api integration
parent
5cde8dbbc6
commit
5c2e3c8979
|
|
@ -97,6 +97,9 @@ export default function HomeScreen() {
|
|||
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerStyle: {
|
||||
backgroundColor: "#F3F5F8",
|
||||
},
|
||||
headerTitle: () => (
|
||||
<View style={styles.headerTitleContainer}>
|
||||
<Text style={styles.title}>{model}</Text>
|
||||
|
|
@ -106,7 +109,7 @@ export default function HomeScreen() {
|
|||
headerRight: () => (
|
||||
<View style={styles.rightContainer}>
|
||||
<Pressable
|
||||
style={styles.iconContainer}
|
||||
style={styles.supportButton}
|
||||
onPress={() => {
|
||||
console.log("Support Pressed");
|
||||
setIsSupportModalVisible(true);
|
||||
|
|
@ -357,6 +360,9 @@ const styles = StyleSheet.create({
|
|||
paddingBottom: 110,
|
||||
},
|
||||
iconContainer: {
|
||||
backgroundColor: "#FCFCFC",
|
||||
},
|
||||
supportButton: {
|
||||
backgroundColor: "#F3F5F8",
|
||||
},
|
||||
headerTitleContainer: {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ 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";
|
||||
|
||||
interface FormValues {
|
||||
serviceType: string | null;
|
||||
|
|
@ -37,6 +42,7 @@ const validationSchema = Yup.object().shape({
|
|||
export default function ServiceFormScreen(): JSX.Element {
|
||||
const [isFocus, setIsFocus] = useState<boolean>(false);
|
||||
const [isIssueSelectorVisible, setIssueSelectorVisible] = useState(false);
|
||||
const { showSnackbar } = useSnackbar();
|
||||
|
||||
function toggleIssueSelector() {
|
||||
setIssueSelectorVisible(!isIssueSelectorVisible);
|
||||
|
|
@ -113,11 +119,44 @@ export default function ServiceFormScreen(): JSX.Element {
|
|||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={(
|
||||
onSubmit={async (
|
||||
values: FormValues,
|
||||
actions: FormikHelpers<FormValues>
|
||||
) => {
|
||||
console.log(values);
|
||||
try {
|
||||
const uploadedPhotoUrls: string[] = [];
|
||||
for (const uri of values.photos) {
|
||||
const uploadedUrl = await uploadImage(uri);
|
||||
uploadedPhotoUrls.push(uploadedUrl);
|
||||
}
|
||||
|
||||
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) {
|
||||
throw new Error(response.data?.message || "Submission failed");
|
||||
}
|
||||
|
||||
console.log("Submission successful:", response.data);
|
||||
|
||||
actions.resetForm();
|
||||
showSnackbar("Service request submitted successfully", "success");
|
||||
} catch (error) {
|
||||
console.error("Error during submission:", error);
|
||||
showSnackbar("Failed to submit service request", "error");
|
||||
} finally {
|
||||
actions.setSubmitting(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{({
|
||||
|
|
@ -128,6 +167,7 @@ export default function ServiceFormScreen(): JSX.Element {
|
|||
setFieldValue,
|
||||
errors,
|
||||
touched,
|
||||
isSubmitting,
|
||||
}) => (
|
||||
<View style={styles.formContainer}>
|
||||
<View style={styles.inputContainer}>
|
||||
|
|
@ -265,6 +305,7 @@ export default function ServiceFormScreen(): JSX.Element {
|
|||
setFieldValue("issues", selectedIssues);
|
||||
}}
|
||||
/>
|
||||
{isSubmitting && <Overlay isUploading={isSubmitting} />}
|
||||
</View>
|
||||
)}
|
||||
</Formik>
|
||||
|
|
|
|||
|
|
@ -18,17 +18,10 @@ import { logout } from "@/store/authSlice";
|
|||
import * as ImagePicker from "expo-image-picker";
|
||||
import { useSnackbar } from "@/contexts/Snackbar";
|
||||
import { AWS, BASE_URL, USER_PROFILE } from "@/constants/config";
|
||||
import { bytesToMB, handleUpload, updateUserProfile } from "@/utils/User";
|
||||
import api from "@/services/axiosClient";
|
||||
import { PresignedUrlDataItem } from "@/utils/User";
|
||||
import { bytesToMB, updateUserProfile, uploadImage } from "@/utils/User";
|
||||
import { setUserData } from "@/store/userSlice";
|
||||
import { Overlay } from "@/components/common/Overlay";
|
||||
|
||||
interface PresignedUrlResponse {
|
||||
message: string;
|
||||
data?: PresignedUrlDataItem[];
|
||||
}
|
||||
|
||||
export default function ProfileScreen() {
|
||||
const [isLangaugeModalVisible, setLanguageModalVisible] =
|
||||
React.useState(false);
|
||||
|
|
@ -51,51 +44,6 @@ export default function ProfileScreen() {
|
|||
router.replace("/auth/login");
|
||||
};
|
||||
|
||||
const uploadImage = async (fileName: string, uri: string) => {
|
||||
try {
|
||||
setIsUploading(true);
|
||||
const getPresignedUrl = `${BASE_URL}/api/v1/generate-presigned-urls`;
|
||||
|
||||
const response = await api.post<PresignedUrlResponse>(getPresignedUrl, {
|
||||
files: [fileName],
|
||||
});
|
||||
|
||||
const uploadData = response?.data?.data?.[0];
|
||||
if (!uploadData) throw new Error("Presigned URL not received");
|
||||
|
||||
const { url, fields, originalFileName } = uploadData;
|
||||
const presignedUrl: PresignedUrlDataItem = {
|
||||
url,
|
||||
fields,
|
||||
originalFileName,
|
||||
};
|
||||
await handleUpload(uri, presignedUrl);
|
||||
|
||||
const region = AWS.REGION;
|
||||
const bucketName = AWS.BUCKET_NAME;
|
||||
const objectKey = presignedUrl.fields.key;
|
||||
|
||||
const uploadedImageUrl = `https://s3.${region}.amazonaws.com/${bucketName}/${encodeURIComponent(
|
||||
objectKey
|
||||
)}`;
|
||||
|
||||
console.log("Uploaded image URL:", uploadedImageUrl);
|
||||
await updateUserProfile({
|
||||
profile_url: uploadedImageUrl,
|
||||
mobile: mobileNumber,
|
||||
});
|
||||
|
||||
dispatch(setUserData({ profile_url: uri }));
|
||||
|
||||
showSnackbar("Image uploaded successfully", "success");
|
||||
} catch (error) {
|
||||
console.error("Error uploading image:", error);
|
||||
showSnackbar("Error uploading image", "error");
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePickImage = async () => {
|
||||
let result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||
|
|
@ -105,25 +53,40 @@ export default function ProfileScreen() {
|
|||
});
|
||||
|
||||
if (!result.canceled) {
|
||||
const { uri, fileSize } = result.assets[0];
|
||||
console.log(uri, "File size:", fileSize);
|
||||
if (!fileSize) {
|
||||
showSnackbar("Image size is not available", "error");
|
||||
return;
|
||||
}
|
||||
const size = bytesToMB(fileSize);
|
||||
if (size > USER_PROFILE.MAX_IMAGE_SIZE_IN_MB) {
|
||||
showSnackbar(
|
||||
`Image size exceeds ${USER_PROFILE.MAX_IMAGE_SIZE_IN_MB}MB limit`,
|
||||
"error"
|
||||
);
|
||||
throw new Error(
|
||||
`Image size exceeds ${USER_PROFILE.MAX_IMAGE_SIZE_IN_MB}MB limit`
|
||||
);
|
||||
}
|
||||
try {
|
||||
setIsUploading(true);
|
||||
const { uri, fileSize } = result.assets[0];
|
||||
console.log(uri, "File size:", fileSize);
|
||||
if (!fileSize) {
|
||||
showSnackbar("Image size is not available", "error");
|
||||
return;
|
||||
}
|
||||
const size = bytesToMB(fileSize);
|
||||
if (size > USER_PROFILE.MAX_IMAGE_SIZE_IN_MB) {
|
||||
showSnackbar(
|
||||
`Image size exceeds ${USER_PROFILE.MAX_IMAGE_SIZE_IN_MB}MB limit`,
|
||||
"error"
|
||||
);
|
||||
throw new Error(
|
||||
`Image size exceeds ${USER_PROFILE.MAX_IMAGE_SIZE_IN_MB}MB limit`
|
||||
);
|
||||
}
|
||||
const uploadedImageUrl = await uploadImage(uri);
|
||||
|
||||
const fileName = uri.split("/").pop() || "image.jpg";
|
||||
await uploadImage(fileName, uri);
|
||||
console.log("Uploaded image URL:", uploadedImageUrl);
|
||||
await updateUserProfile({
|
||||
profile_url: uploadedImageUrl,
|
||||
mobile: mobileNumber,
|
||||
});
|
||||
|
||||
dispatch(setUserData({ profile_url: uri }));
|
||||
showSnackbar("Image uploaded successfully", "success");
|
||||
} catch (error) {
|
||||
console.error("Error uploading image:", error);
|
||||
showSnackbar("Image upload failed", "error");
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ export default function IssueSelectorModal({
|
|||
/>
|
||||
</View>
|
||||
|
||||
{/* Selection Counter and Clear Button */}
|
||||
<View style={styles.counterBar}>
|
||||
<Text
|
||||
style={styles.counterText}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { BASE_URL } from "@/constants/config";
|
||||
import { AWS, BASE_URL } from "@/constants/config";
|
||||
import api from "@/services/axiosClient";
|
||||
import axios from "axios";
|
||||
|
||||
|
|
@ -25,6 +25,11 @@ export function bytesToMB(bytes: number) {
|
|||
return bytes / MB;
|
||||
}
|
||||
|
||||
interface PresignedUrlResponse {
|
||||
message: string;
|
||||
data?: PresignedUrlDataItem[];
|
||||
}
|
||||
|
||||
export const handleUpload = async (
|
||||
uri: string,
|
||||
presignedUrl: PresignedUrlDataItem
|
||||
|
|
@ -125,3 +130,33 @@ export const updateUserProfile = ({
|
|||
|
||||
return api.put(`${BASE_URL}/api/v1/update-user-information`, payload);
|
||||
};
|
||||
|
||||
export const uploadImage = async (uri: string) => {
|
||||
const fileName = uri.split("/").pop() || "image.jpg";
|
||||
const getPresignedUrl = `${BASE_URL}/api/v1/generate-presigned-urls`;
|
||||
|
||||
const response = await api.post<PresignedUrlResponse>(getPresignedUrl, {
|
||||
files: [fileName],
|
||||
});
|
||||
|
||||
const uploadData = response?.data?.data?.[0];
|
||||
if (!uploadData) throw new Error("Presigned URL not received");
|
||||
|
||||
const { url, fields, originalFileName } = uploadData;
|
||||
const presignedUrl: PresignedUrlDataItem = {
|
||||
url,
|
||||
fields,
|
||||
originalFileName,
|
||||
};
|
||||
await handleUpload(uri, presignedUrl);
|
||||
|
||||
const region = AWS.REGION;
|
||||
const bucketName = AWS.BUCKET_NAME;
|
||||
const objectKey = presignedUrl.fields.key;
|
||||
|
||||
const uploadedImageUrl = `https://s3.${region}.amazonaws.com/${bucketName}/${encodeURIComponent(
|
||||
objectKey
|
||||
)}`;
|
||||
|
||||
return uploadedImageUrl;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue