matiru

Blockchain-Based Supply Chain Transparency for Agricultural Produce

frontend/components/ImageUploader.js (2847B)


  1import { useState, forwardRef, useImperativeHandle } from "react";
  2import {
  3  ActivityIndicator,
  4  Alert,
  5  Button,
  6  Image,
  7  Platform,
  8  Text,
  9  View,
 10} from "react-native";
 11import { launchImageLibraryAsync } from "expo-image-picker";
 12import { api } from "../services/api";
 13import { colors } from "../styles";
 14
 15const ImageUploader = forwardRef(({ token }, ref) => {
 16  const [imageAsset, setImageAsset] = useState(null);
 17  const [isUploading, setIsUploading] = useState(false);
 18
 19  useImperativeHandle(ref, () => ({
 20    upload: async () => {
 21      if (!imageAsset) return null;
 22      setIsUploading(true);
 23      try {
 24        const imageUrl = await handleUpload();
 25        return imageUrl;
 26      } catch (error) {
 27        Alert.alert("Upload Failed", error.message);
 28        return null;
 29      } finally {
 30        setIsUploading(false);
 31      }
 32    },
 33    reset: () => {
 34      setImageAsset(null);
 35      setIsUploading(false);
 36    },
 37  }));
 38
 39  const pickImage = async () => {
 40    const result = await launchImageLibraryAsync({
 41      allowsEditing: true,
 42      quality: 0.7,
 43      mediaTypes: "Images",
 44    });
 45    if (!result.canceled) setImageAsset(result.assets[0]);
 46  };
 47
 48  const handleUpload = async () => {
 49    const data = new FormData();
 50    if (Platform.OS === "web") {
 51      const response = await fetch(imageAsset.uri);
 52      const blob = await response.blob();
 53      const fileName = imageAsset.fileName || `web-image-${Date.now()}.jpg`;
 54      data.append("image", blob, fileName);
 55    } else {
 56      data.append("image", {
 57        uri: imageAsset.uri,
 58        type: imageAsset.mimeType || "image/jpeg",
 59        name:
 60          imageAsset.fileName ||
 61          imageAsset.uri.split("/").pop() ||
 62          `image-${Date.now()}.jpg`,
 63      });
 64    }
 65    const responseData = await api.uploadImage(data, token);
 66    return responseData.url;
 67  };
 68
 69  const removeImage = () => {
 70    setImageAsset(null);
 71  };
 72
 73  return (
 74    <View style={{ marginVertical: 10 }}>
 75      {imageAsset && (
 76        <View>
 77          <Image
 78            source={{ uri: imageAsset.uri }}
 79            style={{
 80              width: "100%",
 81              height: 200,
 82              resizeMode: "contain",
 83              marginBottom: 10,
 84            }}
 85          />
 86          <Button
 87            title="Remove Image"
 88            color={colors.danger}
 89            onPress={removeImage}
 90          />
 91        </View>
 92      )}
 93
 94      {isUploading ? (
 95        <View style={{ alignItems: "center", padding: 20 }}>
 96          <ActivityIndicator size="large" color={colors.darkGreen} />
 97          <Text>Uploading...</Text>
 98        </View>
 99      ) : (
100        !imageAsset && (
101          <Button
102            title="Pick Image"
103            color={colors.darkGreen}
104            onPress={pickImage}
105          />
106        )
107      )}
108    </View>
109  );
110});
111
112export default ImageUploader;