From 37d2fbe48a54c8fbadc7de68a9e1ac270a57350e Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Thu, 12 Mar 2026 16:50:02 +0800 Subject: [PATCH] Fix code/ User Pages - app/(application)/(user)/home.tsx - app/(application)/(user)/portofolio/[id]/create.tsx Components - components/_ShareComponent/AppHeader.tsx Screens - screens/Portofolio/ScreenPortofolioCreate.tsx Config & Dependencies - app.config.js - package.json - bun.lock iOS - ios/HIPMIBadungConnect.xcodeproj/project.pbxproj - ios/HIPMIBadungConnect/Info.plist Docs - docs/prompt-for-qwen-code.md ### No issue --- app.config.js | 2 +- app/(application)/(user)/home.tsx | 49 ++- .../(user)/portofolio/[id]/create.tsx | 364 +----------------- components/_ShareComponent/AppHeader.tsx | 113 ++++++ docs/prompt-for-qwen-code.md | 8 +- .../project.pbxproj | 108 ++++++ ios/HIPMIBadungConnect/Info.plist | 2 +- screens/Portofolio/ScreenPortofolioCreate.tsx | 340 ++++++++++++++++ 8 files changed, 598 insertions(+), 388 deletions(-) create mode 100644 components/_ShareComponent/AppHeader.tsx create mode 100644 screens/Portofolio/ScreenPortofolioCreate.tsx diff --git a/app.config.js b/app.config.js index e93d76c..e93a654 100644 --- a/app.config.js +++ b/app.config.js @@ -34,7 +34,7 @@ export default { associatedDomains: [ "applinks:cld-dkr-hipmi-stg.wibudev.com", ], - buildNumber: "4", + buildNumber: "5", }, android: { diff --git a/app/(application)/(user)/home.tsx b/app/(application)/(user)/home.tsx index 7f93631..e2c01c7 100644 --- a/app/(application)/(user)/home.tsx +++ b/app/(application)/(user)/home.tsx @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable react-hooks/exhaustive-deps */ import { BasicWrapper, StackCustom, ViewWrapper } from "@/components"; +import AppHeader from "@/components/_ShareComponent/AppHeader"; import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom"; import { MainColor } from "@/constants/color-palet"; import { useAuth } from "@/hooks/use-auth"; @@ -117,28 +118,36 @@ export default function Application() { <> - data ? ( - { - router.push("/user-search"); - }} - /> - ) : ( - - ), - headerRight: () => - data ? ( - - ) : ( - - ), + header: () => ( + { + router.push("/user-search"); + }} + /> + ) : ( + + ) + } + right={ + data ? ( + + ) : ( + + ) + } + /> + ), }} /> + (null); - const [inputValue, setInputValue] = useState(""); - const [data, setData] = useState({ - namaBisnis: "", - masterBidangBisnisId: "", - alamatKantor: "", - tlpn: "", - deskripsi: "", - }); - const [imageUri, setImageUri] = useState(null); - - const [bidangBisnis, setBidangBisnis] = useState([]); - const [subBidangBisnis, setSubBidangBisnis] = useState< - IMasterSubBidangBisnis[] - >([]); - - const [selectedSubBidang, setSelectedSubBidang] = useState([]); - const [listSubBidangSelected, setListSubBidangSelected] = useState([ - { - id: "", - }, - ]); - - const [dataMedsos, setDataMedsos] = useState({ - facebook: "", - twitter: "", - instagram: "", - youtube: "", - tiktok: "", - }); - - const [isLoadingCreate, setIsLoadingCreate] = useState(false); - - function handleInputValue(phoneNumber: string) { - setInputValue(phoneNumber); - const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || ""; - let fixNumber = inputValue.replace(/\s+/g, "").replace(/^0+/, ""); - const realNumber = callingCode + fixNumber; - setData({ ...data, tlpn: realNumber }); - } - - function handleSelectedCountry(country: ICountry) { - setSelectedCountry(country); - } - - useFocusEffect( - useCallback(() => { - onLoadMaster(); - onLoadMasterSubBidangBisnis(); - }, []) - ); - - const onLoadMaster = async () => { - try { - const response = await apiMasterBidangBisnis(); - setBidangBisnis(response.data); - } catch (error) { - setBidangBisnis([]); - console.log("Error onLoadMasterBidangBisnis", error); - } - }; - - const onLoadMasterSubBidangBisnis = async () => { - try { - const response = await apiMasterSubBidangBisnis({}); - setSubBidangBisnis(response.data); - } catch (error) { - setSubBidangBisnis([]); - console.log("Error onLoadMasterBidangBisnis", error); - } - }; - - const handlerSelectedSubBidang = ({ id }: { id: string }) => { - const selectedList = subBidangBisnis?.filter( - (item) => (item?.masterBidangBisnisId as any) === id - ); - setSelectedSubBidang(selectedList as any[]); - }; - - return ( - - } - > - {/* Portofolio Create {id} */} - - - setData({ ...data, namaBisnis: value })} - /> - - ({ - label: item.name, - value: item.id, - }))} - value={data.masterBidangBisnisId} - onChange={(value) => { - const isSameBidang = data.masterBidangBisnisId === value; - - if (!isSameBidang) { - setListSubBidangSelected([{ id: "" }]); - } - - setData({ ...(data as any), masterBidangBisnisId: value }); - handlerSelectedSubBidang({ id: value as string }); - }} - /> - - {listSubBidangSelected.map((item, index) => ( - { - const selectedValues = listSubBidangSelected.map((s) => s.id); - return ( - option.id === item.id || // biarkan tetap muncul kalau ini valuenya sendiri - !selectedValues.includes(option.id) - ); - }) - .map((e: any) => ({ - value: e.id, - label: e.name, - }))} - value={item.id || null} - onChange={(value) => { - const list = _.clone(listSubBidangSelected); - list[index].id = value as any; - setListSubBidangSelected(list); - }} - /> - ))} - - - - { - setListSubBidangSelected([ - ...listSubBidangSelected, - { id: "" }, - ]); - }} - icon={ - - } - size="xl" - /> - { - const list = _.clone(listSubBidangSelected); - list.pop(); - setListSubBidangSelected(list); - }} - icon={ - - } - size="xl" - /> - - - - - {/* ({ - label: item.name, - value: item.id, - }))} - value={null} - onChange={(value) => { - setData({ ...(data as any), masterBidangBisnisId: value }); - handlerSelectedSubBidang({ id: value as string }); - }} - /> */} - - {/* { - setListSubBidangSelected([...listSubBidangSelected, { id: "" }]); - }} - > - Tambah Pilihan - - */} - - {/* {JSON.stringify(bidangBisnis, null, 2)} */} - - - - - Nomor Telepon - - * - - - - - - - - setData({ ...data, alamatKantor: value }) - } - /> - - setData({ ...data, deskripsi: value })} - autosize - minRows={2} - maxRows={5} - required - showCount - maxLength={1000} - /> - - - {/* Logo */} - - - - - - - { - pickImage({ - setImageUri, - }); - }} - > - Upload - - - - {/* Social Media */} - - - setDataMedsos({ ...dataMedsos, tiktok: value }) - } - /> - - setDataMedsos({ ...dataMedsos, facebook: value }) - } - /> - - setDataMedsos({ ...dataMedsos, instagram: value }) - } - /> - - setDataMedsos({ ...dataMedsos, twitter: value }) - } - /> - - setDataMedsos({ ...dataMedsos, youtube: value }) - } - /> - {/* */} - - - ); + return ; } diff --git a/components/_ShareComponent/AppHeader.tsx b/components/_ShareComponent/AppHeader.tsx new file mode 100644 index 0000000..0f318a2 --- /dev/null +++ b/components/_ShareComponent/AppHeader.tsx @@ -0,0 +1,113 @@ +import { MainColor } from "@/constants/color-palet"; +import { Platform, StyleSheet, Text, View } from "react-native"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { BackButton } from ".."; + +type Props = { + title: string; + right?: React.ReactNode; + showBack?: boolean; + onPressLeft?: () => void; + left?: React.ReactNode; +}; + +export default function AppHeader({ + title, + right, + showBack = true, + onPressLeft, + left, +}: Props) { + const insets = useSafeAreaInsets(); + + // iOS 16+ detection (Dynamic Island) - insets.top > 47 indicates Dynamic Island + const isIOS26Plus = + Platform.OS === "ios" && insets.top > 47; + + // Dynamic padding berdasarkan platform dan iOS version + const paddingTop = + Platform.OS === "ios" + ? isIOS26Plus + ? insets.top - 10 + : insets.top + : 10; + + const paddingBottom = Platform.OS === "ios" ? 8 : 13; + + return ( + + {/* Header Container dengan absolute positioning untuk title center */} + + {/* Left Section - Absolute Left */} + + {showBack ? ( + + ) : left ? ( + left + ) : ( + + )} + + + {/* Title - Absolute Center */} + + + {title ? title.charAt(0).toUpperCase() + title.slice(1) : ""} + + + + {/* Right Section - Absolute Right */} + + {right} + + + + ); +} + +const styles = StyleSheet.create({ + headerApp: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + paddingHorizontal: 16, + height: 44, // Fixed height untuk consistency + }, + headerLeft: { + position: "absolute", + left: 16, + zIndex: 1, + }, + headerCenter: { + flex: 1, + alignItems: "center", + justifyContent: "center", + }, + headerRight: { + position: "absolute", + right: 16, + zIndex: 1, + }, + placeholder: { + width: 40, + height: 40, + }, + headerTitle: { + color: MainColor.yellow, + fontSize: 18, + fontWeight: "600", + textAlign: "center", + }, +}); diff --git a/docs/prompt-for-qwen-code.md b/docs/prompt-for-qwen-code.md index d81d1e3..ecc6aa4 100644 --- a/docs/prompt-for-qwen-code.md +++ b/docs/prompt-for-qwen-code.md @@ -55,10 +55,10 @@ Component yang digunakan: components/_ShareComponent/NewWrapper.tsx -File source: app/(application)/admin/event/[id]/[status]/index.tsx -Folder tujuan: screens/Admin/Event -Nama file utama: ScreenEventDetail.tsx -Nama function utama: Admin_ScreenEventDetail +File source: app/(application)/(user)/portofolio/[id]/create.tsx +Folder tujuan: screens/Portofolio +Nama file utama: ScreenPortofolioCreate.tsx +Nama function utama: Admin_ScreenPortofolioCreate File komponen wrapper: components/_ShareComponent/NewWrapper.tsx Buat file baru pada "Folder tujuan" dengan nama "Nama file utama" dan ubah nama function menjadi "Nama function utama" kemudian clean code, import dan panggil function tersebut pada file "File source" diff --git a/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj b/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj index 86618eb..aa8f16f 100644 --- a/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj +++ b/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj @@ -189,6 +189,12 @@ 0D62979D96BF4B99AB9FBE7C /* Remove signature files (Xcode workaround) */, 49B80EF12BE8476C86534CEA /* Remove signature files (Xcode workaround) */, 6218417B3C954EFF9B5F4853 /* Remove signature files (Xcode workaround) */, + 7B5AE3770142492D84AEAAB3 /* Remove signature files (Xcode workaround) */, + 0F1E3753571D42AB932C4F72 /* Remove signature files (Xcode workaround) */, + B020BDE42E304FBD99BD2279 /* Remove signature files (Xcode workaround) */, + 6ECA5F81B0BC4C70A91BE265 /* Remove signature files (Xcode workaround) */, + 44265583B67C48F2A24BA93E /* Remove signature files (Xcode workaround) */, + D5CA1D54CFF74AB4B8B5B583 /* Remove signature files (Xcode workaround) */, ); buildRules = ( ); @@ -1103,6 +1109,108 @@ rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; "; }; + 7B5AE3770142492D84AEAAB3 /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; + 0F1E3753571D42AB932C4F72 /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; + B020BDE42E304FBD99BD2279 /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; + 6ECA5F81B0BC4C70A91BE265 /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; + 44265583B67C48F2A24BA93E /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; + D5CA1D54CFF74AB4B8B5B583 /* Remove signature files (Xcode workaround) */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Remove signature files (Xcode workaround)"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = " + echo \"Remove signature files (Xcode workaround)\"; + rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\"; + "; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/HIPMIBadungConnect/Info.plist b/ios/HIPMIBadungConnect/Info.plist index 4077bf2..7cbdcbd 100644 --- a/ios/HIPMIBadungConnect/Info.plist +++ b/ios/HIPMIBadungConnect/Info.plist @@ -39,7 +39,7 @@ CFBundleVersion - 4 + 5 ITSAppUsesNonExemptEncryption LSMinimumSystemVersion diff --git a/screens/Portofolio/ScreenPortofolioCreate.tsx b/screens/Portofolio/ScreenPortofolioCreate.tsx new file mode 100644 index 0000000..041c8df --- /dev/null +++ b/screens/Portofolio/ScreenPortofolioCreate.tsx @@ -0,0 +1,340 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + ActionIcon, + ButtonCenteredOnly, + CenterCustom, + InformationBox, + NewWrapper, + SelectCustom, + Spacing, + StackCustom, + TextAreaCustom, + TextCustom, + TextInputCustom, +} from "@/components"; +import { MainColor } from "@/constants/color-palet"; +import { ICON_SIZE_XLARGE } from "@/constants/constans-value"; +import DUMMY_IMAGE from "@/constants/dummy-image-value"; +import Portofolio_ButtonCreate from "@/screens/Portofolio/ButtonCreatePortofolio"; +import { + apiMasterBidangBisnis, + apiMasterSubBidangBisnis, +} from "@/service/api-client/api-master"; +import { + IMasterBidangBisnis, + IMasterSubBidangBisnis, +} from "@/types/Type-Master"; +import pickImage from "@/utils/pickImage"; +import { Ionicons } from "@expo/vector-icons"; +import { useFocusEffect, useLocalSearchParams } from "expo-router"; +import _ from "lodash"; +import { useCallback, useState } from "react"; +import { Text, View } from "react-native"; +import PhoneInput, { ICountry } from "react-native-international-phone-number"; +import { Avatar } from "react-native-paper"; + +export function Admin_ScreenPortofolioCreate() { + const { id } = useLocalSearchParams(); + const [selectedCountry, setSelectedCountry] = useState(null); + const [inputValue, setInputValue] = useState(""); + const [data, setData] = useState({ + namaBisnis: "", + masterBidangBisnisId: "", + alamatKantor: "", + tlpn: "", + deskripsi: "", + }); + const [imageUri, setImageUri] = useState(null); + + const [bidangBisnis, setBidangBisnis] = useState([]); + const [subBidangBisnis, setSubBidangBisnis] = useState< + IMasterSubBidangBisnis[] + >([]); + + const [selectedSubBidang, setSelectedSubBidang] = useState([]); + const [listSubBidangSelected, setListSubBidangSelected] = useState([ + { + id: "", + }, + ]); + + const [dataMedsos, setDataMedsos] = useState({ + facebook: "", + twitter: "", + instagram: "", + youtube: "", + tiktok: "", + }); + + const [isLoadingCreate, setIsLoadingCreate] = useState(false); + + useFocusEffect( + useCallback(() => { + onLoadMaster(); + onLoadMasterSubBidangBisnis(); + }, []) + ); + + const onLoadMaster = async () => { + try { + const response = await apiMasterBidangBisnis(); + setBidangBisnis(response.data); + } catch (error) { + setBidangBisnis([]); + console.log("Error onLoadMasterBidangBisnis", error); + } + }; + + const onLoadMasterSubBidangBisnis = async () => { + try { + const response = await apiMasterSubBidangBisnis({}); + setSubBidangBisnis(response.data); + } catch (error) { + setSubBidangBisnis([]); + console.log("Error onLoadMasterSubBidangBisnis", error); + } + }; + + const handlerSelectedSubBidang = ({ id }: { id: string }) => { + const selectedList = subBidangBisnis?.filter( + (item) => (item?.masterBidangBisnisId as any) === id + ); + setSelectedSubBidang(selectedList as any[]); + }; + + const handleInputValue = (phoneNumber: string) => { + setInputValue(phoneNumber); + const callingCode = selectedCountry?.callingCode.replace(/^\+/, "") || ""; + let fixNumber = inputValue.replace(/\s+/g, "").replace(/^0+/, ""); + const realNumber = callingCode + fixNumber; + setData({ ...data, tlpn: realNumber }); + }; + + const handleSelectedCountry = (country: ICountry) => { + setSelectedCountry(country); + }; + + return ( + + } + > + + + + setData({ ...data, namaBisnis: value })} + /> + + ({ + label: item.name, + value: item.id, + }))} + value={data.masterBidangBisnisId} + onChange={(value) => { + const isSameBidang = data.masterBidangBisnisId === value; + + if (!isSameBidang) { + setListSubBidangSelected([{ id: "" }]); + } + + setData({ ...(data as any), masterBidangBisnisId: value }); + handlerSelectedSubBidang({ id: value as string }); + }} + /> + + {listSubBidangSelected.map((item, index) => ( + { + const selectedValues = listSubBidangSelected.map((s) => s.id); + return ( + option.id === item.id || + !selectedValues.includes(option.id) + ); + }) + .map((e: any) => ({ + value: e.id, + label: e.name, + }))} + value={item.id || null} + onChange={(value) => { + const list = _.clone(listSubBidangSelected); + list[index].id = value as any; + setListSubBidangSelected(list); + }} + /> + ))} + + + + { + setListSubBidangSelected([ + ...listSubBidangSelected, + { id: "" }, + ]); + }} + icon={ + + } + size="xl" + /> + { + const list = _.clone(listSubBidangSelected); + list.pop(); + setListSubBidangSelected(list); + }} + icon={ + + } + size="xl" + /> + + + + + + + + + Nomor Telepon + + * + + + + + + + + + setData({ ...data, alamatKantor: value }) + } + /> + + setData({ ...data, deskripsi: value })} + autosize + minRows={2} + maxRows={5} + required + showCount + maxLength={1000} + /> + + + + + + + + + + + + { + pickImage({ + setImageUri, + }); + }} + > + Upload + + + + + + + + setDataMedsos({ ...dataMedsos, tiktok: value }) + } + /> + + + setDataMedsos({ ...dataMedsos, facebook: value }) + } + /> + + + setDataMedsos({ ...dataMedsos, instagram: value }) + } + /> + + + setDataMedsos({ ...dataMedsos, twitter: value }) + } + /> + + + setDataMedsos({ ...dataMedsos, youtube: value }) + } + /> + + + ); +}