diff --git a/.gitignore b/.gitignore index c9d575d..d2805ed 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ yarn-error.* *.tsbuildinfo app-example + +x.ts +x.sh diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b85249e..2351808 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ + diff --git a/app/(application)/banner/create.tsx b/app/(application)/banner/create.tsx index 485681f..9369a79 100644 --- a/app/(application)/banner/create.tsx +++ b/app/(application)/banner/create.tsx @@ -11,6 +11,13 @@ import { router, Stack } from "expo-router"; import { useState } from "react"; import { Image, Platform, Pressable, SafeAreaView, ScrollView, Text, View } from "react-native"; import { useDispatch } from "react-redux"; +import * as FileSystem from 'expo-file-system'; +import axios from "axios"; +import ReactNativeBlobUtil from 'react-native-blob-util'; +import FormData from 'form-data'; + +const debug = true + export default function CreateBanner() { const { decryptToken, token } = useAuthSession() @@ -20,39 +27,80 @@ export default function CreateBanner() { const [title, setTitle] = useState('') const pickImageAsync = async () => { + kirim() + return let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: false, quality: 1, }); + const formData = new FormData() + formData.append('file', result.assets![0].uri) + + if (debug) console.log("[mengirim gambar]") + const res = await fetch("http://10.0.2.2:3000/api/v2/test", { + method: "POST", + body: formData, + + }); + + console.log("[res]", await res.json()) + + if (debug) console.log("[pickImageAsync]") + if (!result.canceled) { - setSelectedImage(result.assets[0].uri); - setImgForm(result.assets[0]) + if (result.assets?.[0].uri) { + // setSelectedImage(result.assets[0].uri); + // setImgForm(result.assets[0]) + + const formData = new FormData() + formData.append('file', result.assets[0].uri) + + if (debug) console.log("[mengirim gambar]") + const res = await fetch("http://10.0.2.2:3000/api/v2/test", { + method: "POST", + body: formData, + + }); + + console.log("[res]", await res.json()) + + } else { + if (debug) console.log("[pickImageAsync]", 'Tidak ada gambar yang dipilih'); + alert('Tidak ada gambar yang dipilih'); + } + console.log("[imgForm]", imgForm) } else { + if (debug) console.log("[pickImageAsync]", 'Tidak ada gambar yang dipilih'); alert('Tidak ada gambar yang dipilih'); } + + }; - console.log(imgForm) + + const handleCreateEntity = async () => { - const hasil = await decryptToken(String(token?.current)) - const fd = new FormData() - fd.append("file", JSON.stringify({ - uri: imgForm.uri, - type: imgForm.mimeType, - name: imgForm.fileName, - size: imgForm.fileSize, - })) - fd.append("data", JSON.stringify( - { - title: title, - user: hasil - } - )) - const createdEntity = await apiCreateBanner(fd); - // console.log('cliene',createdEntity) + // const hasil = await decryptToken(String(token?.current)) + // const fd = new FormData() + + + // fd.append("file", JSON.stringify({ + // uri: imgForm.uri, + // type: imgForm.mimeType, + // name: imgForm.fileName, + // size: imgForm.fileSize, + // })) + // fd.append("data", JSON.stringify( + // { + // title: title, + // user: hasil + // } + // )) + // const createdEntity = await apiCreateBanner(fd); + // console.log("[createdEntity]", createdEntity) // dispatch(addEntity(createdEntity)); }; @@ -89,4 +137,66 @@ export default function CreateBanner() { ) -} \ No newline at end of file +} + +const requestPermission = async () => { + if (Platform.OS !== 'web') { + const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); + if (status !== 'granted') { + alert('Maaf, kami membutuhkan izin untuk mengakses galeri!'); + return false; + } + return true; + } + return true; +}; + + +async function kirim() { + const hasPermission = await requestPermission(); + + if (!hasPermission) { + return; + } + + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + aspect: [4, 3], + quality: 0.8, + }); + + if (!result.canceled) { + const uri = result.assets[0].uri; + console.log("Selected image URI:", uri); + + try { + + const base64Data = await ReactNativeBlobUtil.fs.readFile(uri, 'base64'); + + // Convert base64 to Blob + const blob = new Blob([base64Data], { type: 'image/jpeg' }); + + const formData = new FormData(); + formData.append('file', blob); + formData.append('name', 'bg.png'); + + + console.log("Sending FormData with file URI..."); + + // Kirim request tanpa header Content-Type + const response = await fetch("http://10.0.2.2:3000/api/v2/test", { + method: 'POST', + body: formData as any, + }); + + // console.log("Response status:", response.status); + + } catch (error: any) { + console.error('Error uploading image:', error); + return null; + } + } + return null; +} + + diff --git a/bun.lockb b/bun.lockb index 1bbd813..e52edf2 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index e7828ab..fd81163 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@react-navigation/bottom-tabs": "^7.2.0", "@react-navigation/native": "^7.0.14", "@reduxjs/toolkit": "^2.7.0", + "@types/formidable": "^3.4.5", "axios": "^1.8.4", "crypto-es": "^2.1.0", "crypto-js": "^3.1.9-1", @@ -28,6 +29,7 @@ "expo-blur": "~14.0.3", "expo-constants": "~17.0.7", "expo-document-picker": "^13.0.3", + "expo-file-system": "~18.0.12", "expo-font": "~13.0.4", "expo-haptics": "~14.0.1", "expo-image-picker": "~16.0.6", @@ -40,10 +42,13 @@ "expo-symbols": "~0.2.2", "expo-system-ui": "~4.0.8", "expo-web-browser": "~14.0.2", + "form-data": "^4.0.2", + "formidable": "^3.5.4", "moment": "^2.30.1", "react": "18.3.1", "react-dom": "18.3.1", "react-native": "0.76.7", + "react-native-blob-util": "^0.21.2", "react-native-confirmation-code-field": "^7.4.0", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "~2.20.2", @@ -51,6 +56,7 @@ "react-native-modal": "^14.0.0-rc.1", "react-native-reanimated": "~3.16.1", "react-native-reanimated-carousel": "^4.0.2", + "react-native-render-html": "^6.3.4", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", "react-native-svg": "15.8.0",