Compare commits

..

39 Commits

Author SHA1 Message Date
17396cea68 Merge pull request 'clean-code/11-mar-26' (#62) from clean-code/11-mar-26 into staging
Reviewed-on: #62
2026-03-12 10:58:40 +08:00
fa4c9005de Merge pull request 'add: Admin Event detail screen dan komponen pendukung' (#61) from clean-code/6-mar-26 into staging
Reviewed-on: #61
2026-03-06 16:53:44 +08:00
c86a3f0ffa Merge pull request 'Fix bug home' (#60) from fix-bug/5-mar-26 into staging
Reviewed-on: #60
2026-03-05 16:45:48 +08:00
c2e6ce7b06 Merge pull request 'fix-bug' (#59) from fix-bug/4-mar-26 into staging
Reviewed-on: #59
2026-03-04 16:46:31 +08:00
b1a5be5105 Merge pull request 'fix-maps dan bug' (#58) from fix-maps/2-mar-26 into staging
Reviewed-on: #58
2026-03-02 16:35:45 +08:00
9e902cec6e Merge pull request 'fix-maps' (#57) from fix-maps/26-feb-26 into staging
Reviewed-on: #57
2026-02-26 18:11:13 +08:00
088c46de3e Merge pull request 'fix-ios/25-feb-26' (#56) from fix-ios/25-feb-26 into staging
Reviewed-on: #56
2026-02-25 16:53:06 +08:00
52d8e91eb2 Merge pull request 'fixed-admin/18-feb-26' (#55) from fixed-admin/18-feb-26 into staging
Reviewed-on: #55
2026-02-18 17:35:18 +08:00
064cf18cba Merge pull request 'fixed-admin' (#54) from fixed-admin/14-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/54
2026-02-14 16:26:43 +08:00
435c5834e9 Merge pull request 'Fix Admin' (#53) from fixed-admin/13-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/53
2026-02-13 17:42:40 +08:00
155cfae331 Merge pull request 'fixed-admin' (#52) from fixed-admin/12-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/52
2026-02-12 17:46:35 +08:00
415243ec6d Merge pull request 'Saya telah melakukan serangkaian perubahan penting dalam pengembangan aplikasi HIPMI Mobile, khususnya dalam modul' (#51) from loaddata/10-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/51
2026-02-10 17:35:05 +08:00
2f2b5a460f Merge pull request 'loaddata/9-feb-26' (#50) from loaddata/9-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/50
2026-02-09 17:40:13 +08:00
b5b4e0816c Merge pull request 'Fix Loaddata Invesment & Clearing code' (#49) from loaddata/6-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/49
2026-02-06 17:29:14 +08:00
32eee66a41 Merge pull request 'loaddata & fix wrapper ui' (#48) from loaddata/5-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/48
2026-02-05 17:37:28 +08:00
3ad8fba6d2 Merge pull request 'loaddata/4-feb-26' (#47) from loaddata/4-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/47
2026-02-05 10:10:25 +08:00
a7022e5afd Merge pull request 'loaddata event' (#46) from loaddata/3-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/46
2026-02-04 10:45:04 +08:00
0cacb5f7de Merge pull request 'Fix Load data pada halaman yang membutuhkan infinite load' (#45) from loaddata/2-feb-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/45
2026-02-02 17:12:28 +08:00
03f53d7b48 Merge pull request 'loaddata/30-jan-26' (#44) from loaddata/30-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/44
2026-01-30 17:21:49 +08:00
c4859b7e82 Merge pull request 'Donation – User' (#43) from notification/27-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/43
2026-01-27 17:44:27 +08:00
e4a66f3bc3 Merge pull request 'notification donation & EULA Logic' (#42) from notification/23-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/42
2026-01-23 17:14:30 +08:00
6d352dd091 Merge pull request 'notification invesment' (#41) from notification/21-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/41
2026-01-21 15:42:52 +08:00
0f62243410 Merge pull request 'notification forum' (#40) from notification/19-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/40
2026-01-20 10:41:06 +08:00
4f32d522a4 Merge pull request 'notification event dan voting' (#39) from notification/15-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/39
2026-01-15 17:42:33 +08:00
1357dff2e3 Merge pull request 'Penerapan Notif & Resolve bug' (#38) from notification/14-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/38
2026-01-14 17:42:33 +08:00
0ba77e5160 Merge pull request 'Perbaikan untuk apple store dan push notifikasi' (#37) from notification/12-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/37
2026-01-12 17:42:12 +08:00
186c667016 Merge pull request 'notification job & EULA metode' (#36) from notification/9-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/36
2026-01-09 17:48:42 +08:00
16f4bf0e62 Merge pull request 'Fix job notifikasi' (#35) from notification/7-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/35
2026-01-08 15:26:01 +08:00
d66dab1a6f Merge pull request 'notification' (#34) from notification/6-jan-26 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/34
2026-01-06 17:49:21 +08:00
e9b6c54c6e Merge pull request 'Notifikasi : Foreground & Background' (#33) from notification/24-dec-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/33
2025-12-24 17:46:13 +08:00
f201f61ce1 Merge pull request 'Filter console dan clean code' (#32) from notification/17-dec-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/32
2025-12-18 11:22:22 +08:00
e407598c7b Merge pull request 'Penerapan ke database' (#31) from notification/16-dec-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/31
2025-12-16 18:01:25 +08:00
c8e2119e99 Merge pull request 'Percobaan notfikasi' (#30) from notification/15-dec-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/30
2025-12-15 17:51:41 +08:00
a287d5545f Merge pull request 'notification/12-dec-25' (#29) from notification/12-dec-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/29
2025-12-12 17:51:58 +08:00
12034ebbfb Merge pull request 'Delete Account' (#15) from delete-account/19-nov-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/15
2025-11-19 17:47:52 +08:00
359daf4e4b Merge pull request 'Try to notification' (#13) from qc/18-nov-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/13
2025-11-18 17:48:03 +08:00
4f0cd3df02 Merge pull request 'Fix rejected apple delete account & start for notification' (#12) from qc/18-nov-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/12
2025-11-18 15:14:10 +08:00
a614cfaac9 Merge pull request 'QR Code & Notification' (#10) from qc/14-nov-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/10
2025-11-14 17:45:29 +08:00
1a7ad58505 Merge pull request 'QR Code Scan' (#9) from qrcode-access/13-nov-25 into staging
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/9
2025-11-13 17:43:08 +08:00
8 changed files with 388 additions and 598 deletions

View File

@@ -34,7 +34,7 @@ export default {
associatedDomains: [
"applinks:cld-dkr-hipmi-stg.wibudev.com",
],
buildNumber: "5",
buildNumber: "4",
},
android: {

View File

@@ -1,7 +1,6 @@
/* 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";
@@ -118,36 +117,28 @@ export default function Application() {
<>
<Stack.Screen
options={{
header: () => (
<AppHeader
title="HIPMI"
showBack={false}
left={
data ? (
<Ionicons
name="search"
size={20}
color={MainColor.yellow}
onPress={() => {
router.push("/user-search");
}}
/>
) : (
<CustomSkeleton height={30} width={30} radius={100} />
)
}
right={
data ? (
<HeaderBell />
) : (
<CustomSkeleton height={30} width={30} radius={100} />
)
}
/>
),
title: `HIPMI`,
headerLeft: () =>
data ? (
<Ionicons
name="search"
size={20}
color={MainColor.yellow}
onPress={() => {
router.push("/user-search");
}}
/>
) : (
<CustomSkeleton height={30} width={30} radius={100} />
),
headerRight: () =>
data ? (
<HeaderBell />
) : (
<CustomSkeleton height={30} width={30} radius={100} />
),
}}
/>
<ViewWrapper
refreshControl={
<RefreshControl

View File

@@ -1,5 +1,365 @@
import { Admin_ScreenPortofolioCreate } from "@/screens/Portofolio/ScreenPortofolioCreate";
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
ActionIcon,
AvatarComp,
BaseBox,
ButtonCenteredOnly,
CenterCustom,
Grid,
InformationBox,
NewWrapper,
SelectCustom,
Spacing,
StackCustom,
TextAreaCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import { IconPlus } from "@/components/_Icon";
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 { Image } from "expo-image";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useCallback, useEffect, useState } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import PhoneInput, { ICountry } from "react-native-international-phone-number";
import { Avatar } from "react-native-paper";
export default function PortofolioCreate() {
return <Admin_ScreenPortofolioCreate />;
const { id } = useLocalSearchParams();
const [selectedCountry, setSelectedCountry] = useState<null | ICountry>(null);
const [inputValue, setInputValue] = useState<string>("");
const [data, setData] = useState({
namaBisnis: "",
masterBidangBisnisId: "",
alamatKantor: "",
tlpn: "",
deskripsi: "",
});
const [imageUri, setImageUri] = useState<string | null>(null);
const [bidangBisnis, setBidangBisnis] = useState<IMasterBidangBisnis[]>([]);
const [subBidangBisnis, setSubBidangBisnis] = useState<
IMasterSubBidangBisnis[]
>([]);
const [selectedSubBidang, setSelectedSubBidang] = useState<string[]>([]);
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 (
<NewWrapper
footerComponent={
<Portofolio_ButtonCreate
id={id as string}
data={data}
dataMedsos={dataMedsos}
imageUri={imageUri}
subBidangSelected={listSubBidangSelected}
isLoadingCreate={isLoadingCreate}
setIsLoadingCreate={setIsLoadingCreate}
/>
}
>
{/* <TextCustom>Portofolio Create {id}</TextCustom> */}
<StackCustom gap={"xs"}>
<InformationBox text="Lengkapi data bisnis anda." />
<TextInputCustom
required
label="Nama Bisnis"
placeholder="Masukkan nama bisnis"
onChangeText={(value: any) => setData({ ...data, namaBisnis: value })}
/>
<SelectCustom
label="Bidang Usaha"
required
data={bidangBisnis.map((item) => ({
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) => (
<SelectCustom
key={index}
disabled={data.masterBidangBisnisId === ""}
label="Sub Bidang Usaha"
required
data={_.map(selectedSubBidang as any)
.filter((option: any) => {
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);
}}
/>
))}
<CenterCustom>
<View style={{ flexDirection: "row", alignItems: "center", gap: 10 }}>
<ActionIcon
disabled={
selectedSubBidang.length === listSubBidangSelected.length
}
onPress={() => {
setListSubBidangSelected([
...listSubBidangSelected,
{ id: "" },
]);
}}
icon={
<Ionicons
name="add-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
<ActionIcon
disabled={listSubBidangSelected.length <= 1}
onPress={() => {
const list = _.clone(listSubBidangSelected);
list.pop();
setListSubBidangSelected(list);
}}
icon={
<Ionicons
name="remove-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
</View>
</CenterCustom>
<Spacing />
{/* <SelectCustom
label="Bidang Usaha"
required
data={bidangBisnis.map((item) => ({
label: item.name,
value: item.id,
}))}
value={null}
onChange={(value) => {
setData({ ...(data as any), masterBidangBisnisId: value });
handlerSelectedSubBidang({ id: value as string });
}}
/> */}
{/* <ButtonCenteredOnly
onPress={() => {
setListSubBidangSelected([...listSubBidangSelected, { id: "" }]);
}}
>
Tambah Pilihan
</ButtonCenteredOnly>
<Spacing /> */}
{/* <TextCustom>{JSON.stringify(bidangBisnis, null, 2)}</TextCustom> */}
<View>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<TextCustom semiBold style={{ color: MainColor.white_gray }}>
Nomor Telepon
</TextCustom>
<Text style={{ color: "red" }}> *</Text>
</View>
<Spacing height={5} />
<PhoneInput
value={inputValue}
onChangePhoneNumber={handleInputValue}
selectedCountry={selectedCountry}
onChangeSelectedCountry={handleSelectedCountry}
defaultCountry="ID"
placeholder="xxx-xxx-xxx"
/>
</View>
<Spacing />
<TextInputCustom
required
label="Alamat Bisnis"
placeholder="Masukkan alamat bisnis"
onChangeText={(value: any) =>
setData({ ...data, alamatKantor: value })
}
/>
<TextAreaCustom
label="Deskripsi Bisnis"
placeholder="Masukkan deskripsi bisnis"
value={data.deskripsi}
onChangeText={(value: any) => setData({ ...data, deskripsi: value })}
autosize
minRows={2}
maxRows={5}
required
showCount
maxLength={1000}
/>
<Spacing />
{/* Logo */}
<InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." />
<CenterCustom>
<Avatar.Image
source={imageUri ? { uri: imageUri } : DUMMY_IMAGE.dummy_image}
size={200}
/>
</CenterCustom>
<Spacing />
<ButtonCenteredOnly
icon="upload"
onPress={() => {
pickImage({
setImageUri,
});
}}
>
Upload
</ButtonCenteredOnly>
<Spacing height={40} />
{/* Social Media */}
<InformationBox text="Isi hanya pada sosial media yang anda miliki." />
<TextInputCustom
label="Tiktok"
placeholder="Masukkan username tiktok"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, tiktok: value })
}
/>
<TextInputCustom
label="Facebook"
placeholder="Masukkan username facebook"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, facebook: value })
}
/>
<TextInputCustom
label="Instagram"
placeholder="Masukkan username instagram"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, instagram: value })
}
/>
<TextInputCustom
label="Twitter"
placeholder="Masukkan username twitter"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, twitter: value })
}
/>
<TextInputCustom
label="Youtube"
placeholder="Masukkan username youtube"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, youtube: value })
}
/>
{/* <Spacing /> */}
</StackCustom>
</NewWrapper>
);
}

View File

@@ -1,113 +0,0 @@
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 (
<View
style={[
{
backgroundColor: MainColor.darkblue,
paddingTop,
paddingBottom,
},
]}
>
{/* Header Container dengan absolute positioning untuk title center */}
<View style={styles.headerApp}>
{/* Left Section - Absolute Left */}
<View style={styles.headerLeft}>
{showBack ? (
<BackButton onPress={onPressLeft} />
) : left ? (
left
) : (
<View style={styles.placeholder} />
)}
</View>
{/* Title - Absolute Center */}
<View style={styles.headerCenter}>
<Text
style={styles.headerTitle}
numberOfLines={1}
ellipsizeMode="tail"
>
{title ? title.charAt(0).toUpperCase() + title.slice(1) : ""}
</Text>
</View>
{/* Right Section - Absolute Right */}
<View style={styles.headerRight}>
{right}
</View>
</View>
</View>
);
}
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",
},
});

View File

@@ -55,10 +55,10 @@ Component yang digunakan: components/_ShareComponent/NewWrapper.tsx
<!-- START Prompt Admin Refactoring -->
<!-- Pindah kode ke Screen Component -->
File source: app/(application)/(user)/portofolio/[id]/create.tsx
Folder tujuan: screens/Portofolio
Nama file utama: ScreenPortofolioCreate.tsx
Nama function utama: Admin_ScreenPortofolioCreate
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 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"

View File

@@ -189,12 +189,6 @@
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 = (
);
@@ -1109,108 +1103,6 @@
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 */

View File

@@ -39,7 +39,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>5</string>
<string>4</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSMinimumSystemVersion</key>

View File

@@ -1,340 +0,0 @@
/* 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 | ICountry>(null);
const [inputValue, setInputValue] = useState<string>("");
const [data, setData] = useState({
namaBisnis: "",
masterBidangBisnisId: "",
alamatKantor: "",
tlpn: "",
deskripsi: "",
});
const [imageUri, setImageUri] = useState<string | null>(null);
const [bidangBisnis, setBidangBisnis] = useState<IMasterBidangBisnis[]>([]);
const [subBidangBisnis, setSubBidangBisnis] = useState<
IMasterSubBidangBisnis[]
>([]);
const [selectedSubBidang, setSelectedSubBidang] = useState<string[]>([]);
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 (
<NewWrapper
footerComponent={
<Portofolio_ButtonCreate
id={id as string}
data={data}
dataMedsos={dataMedsos}
imageUri={imageUri}
subBidangSelected={listSubBidangSelected}
isLoadingCreate={isLoadingCreate}
setIsLoadingCreate={setIsLoadingCreate}
/>
}
>
<StackCustom gap="xs">
<InformationBox text="Lengkapi data bisnis anda." />
<TextInputCustom
required
label="Nama Bisnis"
placeholder="Masukkan nama bisnis"
onChangeText={(value: any) => setData({ ...data, namaBisnis: value })}
/>
<SelectCustom
label="Bidang Usaha"
required
data={bidangBisnis.map((item) => ({
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) => (
<SelectCustom
key={index}
disabled={data.masterBidangBisnisId === ""}
label="Sub Bidang Usaha"
required
data={_.map(selectedSubBidang as any)
.filter((option: any) => {
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);
}}
/>
))}
<CenterCustom>
<View style={{ flexDirection: "row", alignItems: "center", gap: 10 }}>
<ActionIcon
disabled={selectedSubBidang.length === listSubBidangSelected.length}
onPress={() => {
setListSubBidangSelected([
...listSubBidangSelected,
{ id: "" },
]);
}}
icon={
<Ionicons
name="add-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
<ActionIcon
disabled={listSubBidangSelected.length <= 1}
onPress={() => {
const list = _.clone(listSubBidangSelected);
list.pop();
setListSubBidangSelected(list);
}}
icon={
<Ionicons
name="remove-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
</View>
</CenterCustom>
<Spacing />
<View>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<TextCustom semiBold style={{ color: MainColor.white_gray }}>
Nomor Telepon
</TextCustom>
<Text style={{ color: "red" }}> *</Text>
</View>
<Spacing height={5} />
<PhoneInput
value={inputValue}
onChangePhoneNumber={handleInputValue}
selectedCountry={selectedCountry}
onChangeSelectedCountry={handleSelectedCountry}
defaultCountry="ID"
placeholder="xxx-xxx-xxx"
/>
</View>
<Spacing />
<TextInputCustom
required
label="Alamat Bisnis"
placeholder="Masukkan alamat bisnis"
onChangeText={(value: any) =>
setData({ ...data, alamatKantor: value })
}
/>
<TextAreaCustom
label="Deskripsi Bisnis"
placeholder="Masukkan deskripsi bisnis"
value={data.deskripsi}
onChangeText={(value: any) => setData({ ...data, deskripsi: value })}
autosize
minRows={2}
maxRows={5}
required
showCount
maxLength={1000}
/>
<Spacing />
<InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." />
<CenterCustom>
<Avatar.Image
source={imageUri ? { uri: imageUri } : DUMMY_IMAGE.dummy_image}
size={200}
/>
</CenterCustom>
<Spacing />
<ButtonCenteredOnly
icon="upload"
onPress={() => {
pickImage({
setImageUri,
});
}}
>
Upload
</ButtonCenteredOnly>
<Spacing height={40} />
<InformationBox text="Isi hanya pada sosial media yang anda miliki." />
<TextInputCustom
label="Tiktok"
placeholder="Masukkan username tiktok"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, tiktok: value })
}
/>
<TextInputCustom
label="Facebook"
placeholder="Masukkan username facebook"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, facebook: value })
}
/>
<TextInputCustom
label="Instagram"
placeholder="Masukkan username instagram"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, instagram: value })
}
/>
<TextInputCustom
label="Twitter"
placeholder="Masukkan username twitter"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, twitter: value })
}
/>
<TextInputCustom
label="Youtube"
placeholder="Masukkan username youtube"
onChangeText={(value: any) =>
setDataMedsos({ ...dataMedsos, youtube: value })
}
/>
</StackCustom>
</NewWrapper>
);
}