Fix QC ( Ayu )

Fix:
- modified:   app/(application)/(user)/event/[id]/publish.tsx
- modified:   app/(application)/(user)/event/create.tsx
- modified:   app/(application)/(user)/portofolio/[id]/create.tsx
- modified:   app/(application)/(user)/portofolio/[id]/edit.tsx
- modified:   app/(application)/admin/collaboration/[id]/group.tsx
- modified:   app/(application)/admin/collaboration/group.tsx
- modified:   app/(application)/admin/collaboration/publish.tsx
- modified:   app/(application)/admin/forum/[id]/list-report-comment.tsx
- modified:   app/(application)/admin/forum/[id]/list-report-posting.tsx
- modified:   app/(application)/admin/forum/posting.tsx
- modified:   app/(application)/admin/forum/report-comment.tsx
- modified:   app/(application)/admin/forum/report-posting.tsx
- modified:   app/(application)/admin/voting/[status]/status.tsx
- modified:   app/(application)/admin/voting/history.tsx
- modified:   components/Select/SelectCustom.tsx
- modified:   components/_ShareComponent/GridSpan_4_8.tsx
- modified:   screens/Authentication/LoginView.tsx
- modified:   screens/Collaboration/BoxPublishSection.tsx
- modified:   screens/Event/BoxDetailPublishSection.tsx
- modified:   screens/Home/topFeatureSection.tsx
- modified:   screens/Portofolio/ButtonCreatePortofolio.tsx

Add:
- app/(application)/admin/app-information/business-field/[id]/bidang-update.tsx
- app/(application)/admin/app-information/business-field/[id]/sub-bidang-update.tsx

### No Issue
This commit is contained in:
2025-12-10 17:35:15 +08:00
parent cccb44a835
commit 6f9481c7c9
15 changed files with 512 additions and 111 deletions

View File

@@ -19,7 +19,7 @@ export default {
"NSLocationWhenInUseUsageDescription": "Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
},
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
buildNumber: "13",
buildNumber: "14",
},
android: {

View File

@@ -19,7 +19,7 @@ export default function Application() {
const { token, user, userData } = useAuth();
const [data, setData] = useState<any>();
const [refreshing, setRefreshing] = useState(false);
console.log("[User] >>", JSON.stringify(user?.id, null, 2))
console.log("[User] >>", JSON.stringify(user?.id, null, 2));
// ‼️ Untuk cek apakah: 1. user ada, 2. user punya profile, 3. accept temrs of forum nya ada atau tidak
useFocusEffect(
@@ -32,7 +32,10 @@ export default function Application() {
async function onLoadData() {
const response = await apiUser(user?.id as string);
console.log("[Profile ID]>>", JSON.stringify(response?.data?.Profile?.id, null, 2));
console.log(
"[Profile ID]>>",
JSON.stringify(response?.data?.Profile?.id, null, 2)
);
setData(response.data);
}
@@ -81,6 +84,7 @@ export default function Application() {
),
headerRight: () => (
<Ionicons
disabled={true}
name="notifications"
size={20}
color={MainColor.yellow}

View File

@@ -31,9 +31,9 @@ import {
import pickImage from "@/utils/pickImage";
import { Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image";
import { useLocalSearchParams } from "expo-router";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useEffect, useState } from "react";
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";
@@ -85,10 +85,12 @@ export default function PortofolioCreate() {
setSelectedCountry(country);
}
useEffect(() => {
onLoadMaster();
onLoadMasterSubBidangBisnis();
}, []);
useFocusEffect(
useCallback(() => {
onLoadMaster();
onLoadMasterSubBidangBisnis();
}, [])
);
const onLoadMaster = async () => {
try {

View File

@@ -0,0 +1,129 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { MainColor } from "@/constants/color-palet";
import {
apiAdminMasterBusinessFieldById,
apiAdminMasterBusinessFieldUpdate,
} from "@/service/api-admin/api-master-admin";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import { Switch } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminAppInformation_BusinessFieldDetail() {
const { id } = useLocalSearchParams();
const [data, setData] = useState<any | null>(null);
const [isLoading, setIsLoading] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadDetail();
}, [id])
);
const onLoadDetail = async () => {
try {
const response = await apiAdminMasterBusinessFieldById({
id: id as string,
category: "bidang"
});
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
setData(null);
}
};
const handlerSubmit = async () => {
if (!data.name) {
Toast.show({
type: "error",
text1: "Lengkapi Data",
});
return;
}
try {
setIsLoading(true);
const response = await apiAdminMasterBusinessFieldUpdate({
id: id as string,
data: data,
category: "bidang",
});
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal update data",
});
return;
}
Toast.show({
type: "success",
text1: "Data berhasil di update",
});
router.back();
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
}
};
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
disabled={!data?.name}
isLoading={isLoading}
onPress={() => handlerSubmit()}
>
Update
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
value={data?.name}
onChangeText={(value) => setData({ ...data, name: value })}
/>
<StackCustom
gap={"sm"}
style={{
alignContent: "flex-start",
}}
>
<TextCustom>Status</TextCustom>
<Switch
style={{
alignSelf: "flex-start",
}}
color={MainColor.yellow}
value={data?.active}
onValueChange={(value) => setData({ ...data, active: value })}
/>
</StackCustom>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -1,22 +1,22 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BoxButtonOnFooter,
ButtonCustom,
ActionIcon,
BaseBox,
CenterCustom,
LoaderCustom,
Spacing,
StackCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import { IconEdit } from "@/components/_Icon";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
import { MainColor } from "@/constants/color-palet";
import {
apiAdminMasterBusinessFieldById,
apiAdminMasterBusinessFieldUpdate,
} from "@/service/api-admin/api-master-admin";
import { apiAdminMasterBusinessFieldById } from "@/service/api-admin/api-master-admin";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import { Switch } from "react-native-paper";
import Toast from "react-native-toast-message";
import { Divider } from "react-native-paper";
export default function AdminAppInformation_BusinessFieldDetail() {
const { id } = useLocalSearchParams();
@@ -33,8 +33,11 @@ export default function AdminAppInformation_BusinessFieldDetail() {
try {
const response = await apiAdminMasterBusinessFieldById({
id: id as string,
category: "all",
});
console.log("Response >>", JSON.stringify(response, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
@@ -42,73 +45,89 @@ export default function AdminAppInformation_BusinessFieldDetail() {
}
};
const handlerSubmit = async () => {
if (!data.name) {
Toast.show({
type: "error",
text1: "Lengkapi Data",
});
return;
}
try {
setIsLoading(true);
const response = await apiAdminMasterBusinessFieldUpdate({
id: id as string,
data: data,
});
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal update data",
});
return;
}
Toast.show({
type: "success",
text1: "Data berhasil di update",
});
router.back();
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
}
};
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
disabled={!data?.name}
isLoading={isLoading}
onPress={() => handlerSubmit()}
>
Update
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<ViewWrapper>
<StackCustom>
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
<AdminBackButtonAntTitle title="Detail Bidang & Sub Bidang" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
value={data?.name}
onChangeText={(value) => setData({ ...data, name: value })}
/>
{!data ? (
<LoaderCustom />
) : (
<StackCustom gap={"xs"}>
<TextCustom bold>Nama Bidang</TextCustom>
<Spacing height={5} />
<BaseBox>
<StackCustom gap={"xs"}>
<TextCustom bold>
Status: {data?.bidang?.active ? "Aktif" : "Tidak Aktif"}
</TextCustom>
<GridSpan_NewComponent
span1={10}
span2={2}
text1={
<TextCustom bold size={"large"}>
{data?.bidang?.name}
</TextCustom>
}
text2={
<CenterCustom>
<ActionIcon
icon={<IconEdit size={16} color={MainColor.black} />}
onPress={() =>
router.push(
`/admin/app-information/business-field/${id}/bidang-update`
)
}
/>
</CenterCustom>
}
/>
</StackCustom>
</BaseBox>
{/* <Divider /> */}
<Spacing height={5} />
<TextCustom>Status Aktivasi</TextCustom>
<Switch
color={MainColor.yellow}
value={data?.active}
onValueChange={(value) => setData({ ...data, active: value })}
/>
<TextCustom bold>Sub Bidang Bisnis</TextCustom>
<Spacing height={5} />
{data?.subBidang?.map((item: any, index: number) => (
<BaseBox key={index}>
<StackCustom gap={0}>
<TextCustom bold>
Status: {item?.isActive ? "Aktif" : "Tidak Aktif"}
</TextCustom>
<GridSpan_NewComponent
span1={10}
span2={2}
text1={
<TextCustom bold size={"large"}>
{item.name}
</TextCustom>
}
text2={
<CenterCustom>
<ActionIcon
icon={
<IconEdit size={16} color={MainColor.black} />
}
onPress={() =>
router.push(
`/admin/app-information/business-field/${item?.id}/sub-bidang-update`
)
}
/>
</CenterCustom>
}
/>
</StackCustom>
</BaseBox>
))}
</StackCustom>
)}
{/* <TextCustom>{JSON.stringify(data, null, 2)}</TextCustom> */}
</StackCustom>
</ViewWrapper>
</>

View File

@@ -0,0 +1,135 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { MainColor } from "@/constants/color-palet";
import {
apiAdminMasterBusinessFieldById,
apiAdminMasterBusinessFieldUpdate,
} from "@/service/api-admin/api-master-admin";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import { Switch } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminAppInformation_BusinessFieldDetail() {
const { id } = useLocalSearchParams();
const [data, setData] = useState<any | null>(null);
const [isLoading, setIsLoading] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadDetail();
}, [id])
);
const onLoadDetail = async () => {
try {
const response = await apiAdminMasterBusinessFieldById({
id: id as string,
category: "sub-bidang",
subBidangId: id as string,
});
console.log("Response >>", JSON.stringify(response, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
setData(null);
}
};
const handlerSubmit = async () => {
if (!data.name) {
Toast.show({
type: "error",
text1: "Lengkapi Data",
});
return;
}
try {
setIsLoading(true);
const response = await apiAdminMasterBusinessFieldUpdate({
id: id as string,
data: data,
category: "sub-bidang",
});
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal update data",
});
return;
}
Toast.show({
type: "success",
text1: "Data berhasil di update",
});
router.back();
} catch (error) {
console.log(error);
} finally {
setIsLoading(false);
}
};
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
disabled={!data?.name}
isLoading={isLoading}
onPress={() => handlerSubmit()}
>
Update
</ButtonCustom>
</BoxButtonOnFooter>
);
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
value={data?.name}
onChangeText={(value) => setData({ ...data, name: value })}
/>
<StackCustom
gap={"sm"}
style={{
alignContent: "flex-start",
}}
>
<TextCustom>Status</TextCustom>
<Switch
style={{
alignSelf: "flex-start",
}}
color={MainColor.yellow}
value={data?.isActive}
onValueChange={(value) => setData({ ...data, isActive: value })}
/>
</StackCustom>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -1,40 +1,81 @@
import {
BoxButtonOnFooter,
ButtonCustom,
StackCustom,
TextInputCustom,
ViewWrapper,
ActionIcon,
BoxButtonOnFooter,
ButtonCustom,
CenterCustom,
Grid,
Spacing,
StackCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_XLARGE } from "@/constants/constans-value";
import { apiAdminMasterBusinessFieldCreate } from "@/service/api-admin/api-master-admin";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import _ from "lodash";
import { useState } from "react";
import { View } from "react-native";
import { Divider } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function AdminAppInformation_BusinessFieldCreate() {
const [data, setData] = useState<any>({
const [isLoading, setIsLoading] = useState(false);
const [bidang, setBidang] = useState<any>({
name: "",
});
const [isLoading, setIsLoading] = useState(false);
const [subBidang, setSubBidang] = useState<any[]>([
{
name: "",
},
]);
const handlerSubmit = async () => {
if (!data.name) {
if (!bidang.name) {
Toast.show({
type: "error",
text1: "Lengkapi Data",
});
return;
}
if (subBidang[0].name === "") {
Toast.show({
type: "error",
text1: "Lengkapi Sub Bidang",
});
return;
}
try {
setIsLoading(true);
const response = await apiAdminMasterBusinessFieldCreate({ data: data });
const newData = {
bidang: bidang,
subBidang: subBidang,
};
console.log("[DATA]", newData);
const response = await apiAdminMasterBusinessFieldCreate({
data: newData,
});
console.log("[RESPONSE]", response);
if (response.success) {
Toast.show({
type: "success",
text1: "Data berhasil di tambah",
});
router.back();
// router.back();
} else {
Toast.show({
type: "error",
text1: "Gagal tambah data",
});
}
} catch (error) {
console.log("[ERROR]", error);
@@ -50,6 +91,7 @@ export default function AdminAppInformation_BusinessFieldCreate() {
const buttonSubmit = (
<BoxButtonOnFooter>
<ButtonCustom
disabled={subBidang[0].name === ""}
onPress={() => handlerSubmit()}
isLoading={isLoading}
>
@@ -60,16 +102,70 @@ export default function AdminAppInformation_BusinessFieldCreate() {
return (
<>
<ViewWrapper footerComponent={buttonSubmit}>
<StackCustom>
<StackCustom gap={"xs"}>
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
<TextInputCustom
label="Nama Bidang Bisnis"
placeholder="Masukan Nama Bidang Bisnis"
required
value={data.name}
onChangeText={(value) => setData({ ...data, name: value })}
value={bidang.name}
onChangeText={(value) => setBidang({ ...bidang, name: value })}
/>
<Divider />
<Spacing height={5} />
{subBidang.map((item, index) => (
<TextInputCustom
key={index}
label="Nama Sub Bidang"
placeholder="Masukan Nama Sub Bidang"
required
value={item.name}
onChangeText={(value) => {
const list = _.clone(subBidang);
list[index].name = value;
setSubBidang(list);
}}
/>
))}
<CenterCustom>
<View
style={{ flexDirection: "row", alignItems: "center", gap: 10 }}
>
<ActionIcon
onPress={() => {
setSubBidang([...subBidang, { name: "" }]);
}}
icon={
<Ionicons
name="add-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
<ActionIcon
disabled={subBidang.length <= 1}
onPress={() => {
const list = _.clone(subBidang);
list.pop();
setSubBidang(list);
}}
icon={
<Ionicons
name="remove-circle-outline"
size={ICON_SIZE_XLARGE}
color={MainColor.black}
/>
}
size="xl"
/>
</View>
</CenterCustom>
</StackCustom>
</ViewWrapper>
</>

View File

@@ -75,7 +75,7 @@ const listPage = [
},
{
id: "2",
label: "Bidang Bisnis",
label: "Bidang & Sub Bidang",
value: "business",
},
{

View File

@@ -76,7 +76,7 @@ export default function SuperAdmin_ListUser() {
</TextCustom>
}
component2={
<TextCustom align="center" bold>
<TextCustom bold>
Username
</TextCustom>
}

View File

@@ -73,11 +73,7 @@ export default function AdminUserAccess() {
Aksi
</TextCustom>
}
component2={
<TextCustom align="center" bold>
Username
</TextCustom>
}
component2={<TextCustom bold>Username</TextCustom>}
component3={
<TextCustom align="center" bold>
Status Akses

View File

@@ -22,7 +22,7 @@ export const GridSpan_NewComponent = ({
style={{
justifyContent: "flex-start",
paddingRight: 5,
paddingLeft: 5,
paddingLeft: 3,
}}
>
{text1}

View File

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

View File

@@ -134,10 +134,10 @@ export default function LoginView() {
if (token && token !== "" && isAdmin) {
// Akan di aktifkan jika sudah losos review
return <Redirect href={"/(application)/admin/dashboard"} />;
// return <Redirect href={"/(application)/admin/dashboard"} />;
// Sementara gunakan ini
// return <Redirect href={"/(application)/(user)/home"} />;
return <Redirect href={"/(application)/(user)/home"} />;
}
return (

View File

@@ -15,7 +15,7 @@ export default function Home_FeatureSection() {
name: "Collaboration",
icon: <Ionicons name="share" size={48} color="gray" />,
onPress: () => router.push("/(application)/(user)/collaboration/(tabs)"),
status: "active",
status: "inactive",
},
{
name: "Voting",

View File

@@ -60,10 +60,20 @@ export async function apiAdminMasterBusinessField() {
}
}
export async function apiAdminMasterBusinessFieldById({ id }: { id: string }) {
export async function apiAdminMasterBusinessFieldById({
id,
subBidangId,
category,
}: {
id: string;
subBidangId?: string | null;
category: "bidang" | "sub-bidang" | "all";
}) {
const queryCategory = category ? `?category=${category}` : "";
const querySubBidang = subBidangId ? `&subBidangId=${subBidangId}` : "";
try {
const response = await apiConfig.get(
`/mobile/admin/master/business-field/${id}`
`/mobile/admin/master/business-field/${id}${queryCategory}${querySubBidang}`
);
return response.data;
} catch (error) {
@@ -74,13 +84,15 @@ export async function apiAdminMasterBusinessFieldById({ id }: { id: string }) {
export async function apiAdminMasterBusinessFieldUpdate({
id,
data,
category,
}: {
id: string;
data: any;
category: "bidang" | "sub-bidang";
}) {
try {
const response = await apiConfig.put(
`/mobile/admin/master/business-field/${id}`,
`/mobile/admin/master/business-field/${id}?category=${category}`,
{
data: data,
}
@@ -179,7 +191,11 @@ export async function apiAdminMasterDonationCategory() {
}
}
export async function apiAdminMasterDonationCategoryById({ id }: { id: string }) {
export async function apiAdminMasterDonationCategoryById({
id,
}: {
id: string;
}) {
try {
const response = await apiConfig.get(`/mobile/admin/master/donation/${id}`);
return response.data;
@@ -208,7 +224,11 @@ export async function apiAdminMasterDonationCategoryUpdate({
}
}
export async function apiAdminMasterDonationCategoryCreate({ data }: { data: any }) {
export async function apiAdminMasterDonationCategoryCreate({
data,
}: {
data: any;
}) {
try {
const response = await apiConfig.post(`/mobile/admin/master/donation`, {
data: data,