165 lines
5.0 KiB
JavaScript
165 lines
5.0 KiB
JavaScript
import cleanAxios from "@/util/CleanAxios";
|
|
import axios from "axios";
|
|
import { useGlobalSearchParams } from "expo-router";
|
|
import React, { useCallback, useEffect, useState } from "react";
|
|
import { FlatList, RefreshControl, TouchableOpacity, View } from "react-native";
|
|
import ImageView from "react-native-image-viewing";
|
|
import { ActivityIndicator, Text } from "react-native-paper";
|
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
import { connect } from "react-redux";
|
|
import { createStructuredSelector } from "reselect";
|
|
import env from "../../env";
|
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
import { DetermineFileType } from "../../util/document-upload.utility";
|
|
import ErrorDisplay from "../error/error-display";
|
|
import ImageLoader from "./image-loader";
|
|
|
|
const mapStateToProps = createStructuredSelector({
|
|
bodyshop: selectBodyshop,
|
|
});
|
|
const mapDispatchToProps = (dispatch) => ({});
|
|
export default connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(JobDocumentsComponent);
|
|
|
|
export function JobDocumentsComponent({ bodyshop }) {
|
|
const [previewVisible, setPreviewVisible] = useState(false);
|
|
const [fullphotos, setFullPhotos] = useState([]);
|
|
const [imgIndex, setImgIndex] = useState(0);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState(null);
|
|
const { jobId } = useGlobalSearchParams();
|
|
|
|
const isLms = bodyshop.uselocalmediaserver;
|
|
const onRefresh = async () => {
|
|
return getPhotos();
|
|
};
|
|
|
|
const getPhotos = useCallback(async () => {
|
|
setError(null);
|
|
setLoading(true);
|
|
try {
|
|
if (!isLms) {
|
|
const result = await axios.post(
|
|
`${env.API_URL}/media/imgproxy/thumbnails`,
|
|
{
|
|
jobid: jobId,
|
|
}
|
|
);
|
|
|
|
setFullPhotos(
|
|
result.data.map((doc, idx) => {
|
|
return {
|
|
id: idx,
|
|
videoUrl:
|
|
DetermineFileType(doc.type) === "video" &&
|
|
doc.originalUrlViaProxyPath,
|
|
source:
|
|
DetermineFileType(doc.type) === "video"
|
|
? { uri: doc.thumbnailUrl }
|
|
: { uri: doc.originalUrl },
|
|
url:
|
|
DetermineFileType(doc.type) === "video"
|
|
? doc.thumbnailUrl
|
|
: doc.originalUrl,
|
|
uri:
|
|
DetermineFileType(doc.type) === "video"
|
|
? doc.originalUrlViaProxyPath
|
|
: doc.originalUrl,
|
|
thumbUrl: doc.thumbnailUrl,
|
|
};
|
|
})
|
|
);
|
|
} else {
|
|
let localmediaserverhttp = bodyshop.localmediaserverhttp.trim();
|
|
if (localmediaserverhttp.endsWith("/")) {
|
|
localmediaserverhttp = localmediaserverhttp.slice(0, -1);
|
|
}
|
|
|
|
const imagesFetch = await cleanAxios.post(
|
|
`${localmediaserverhttp}/jobs/list`,
|
|
{
|
|
jobid: jobId,
|
|
},
|
|
{ headers: { ims_token: bodyshop.localmediatoken } }
|
|
);
|
|
|
|
const normalizedImages = imagesFetch.data
|
|
.filter((d) => d.type?.mime?.startsWith("image"))
|
|
.map((d, idx) => {
|
|
return {
|
|
...d,
|
|
// src: `${localmediaserverhttp}/${d.src}`,
|
|
|
|
uri: `${localmediaserverhttp}${d.src}`,
|
|
thumbUrl: `${localmediaserverhttp}${d.thumbnail}`,
|
|
id: idx,
|
|
};
|
|
});
|
|
|
|
setFullPhotos(normalizedImages);
|
|
}
|
|
} catch (error) {
|
|
setError(error.message || "Unknown error fetching photos.");
|
|
}
|
|
setLoading(false);
|
|
}, [isLms, jobId, bodyshop]);
|
|
|
|
useEffect(() => {
|
|
getPhotos();
|
|
}, [getPhotos]);
|
|
|
|
if (loading) return <ActivityIndicator style={{ flex: 1 }} size="large" />;
|
|
if (error) {
|
|
return <ErrorDisplay message={JSON.stringify(error)} />;
|
|
}
|
|
|
|
return (
|
|
<View style={{ flex: 1 }}>
|
|
<FlatList
|
|
refreshControl={
|
|
<RefreshControl refreshing={loading} onRefresh={onRefresh} />
|
|
}
|
|
data={fullphotos}
|
|
ListFooterComponent={
|
|
<Text style={{ textAlign: "center", padding: 8 }}>{`${
|
|
fullphotos.length
|
|
} document${fullphotos.length === 1 ? "" : "s"}`}</Text>
|
|
}
|
|
numColumns={4}
|
|
style={{ flex: 1 }}
|
|
keyExtractor={(item) => item.id}
|
|
renderItem={(object) => (
|
|
<TouchableOpacity
|
|
style={{ flex: 1 / 4, aspectRatio: 1, margin: 4 }}
|
|
onPress={async () => {
|
|
setImgIndex(object.index);
|
|
setPreviewVisible(true);
|
|
}}
|
|
>
|
|
<ImageLoader
|
|
style={{ flex: 1 }}
|
|
resizeMode="cover"
|
|
source={{
|
|
uri: object.item.thumbUrl,
|
|
aspectRatio: 1,
|
|
}}
|
|
/>
|
|
</TouchableOpacity>
|
|
)}
|
|
/>
|
|
|
|
<SafeAreaView>
|
|
<ImageView
|
|
onRequestClose={() => setPreviewVisible(false)}
|
|
visible={previewVisible}
|
|
images={fullphotos}
|
|
imageIndex={imgIndex}
|
|
swipeToCloseEnabled={true}
|
|
/>
|
|
</SafeAreaView>
|
|
</View>
|
|
);
|
|
}
|