From 1ee9bea65ed8c14ecc92a7f13dfc6c8e9dbdd889 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Fri, 15 Aug 2025 11:47:43 +0800 Subject: [PATCH 1/5] upd: laporan kegiatan Deskripsi : - tampilan list laporan pada project dan task divisi - tampilan form update laporan pada project dan task divisi - integrasi api update laporan pada project dan task divisi - integrasi api view laporan pada project dan task divisi NO Issues' --- .../(fitur-division)/task/[detail]/index.tsx | 10 +- .../(fitur-division)/task/[detail]/report.tsx | 129 ++++++++++++++++++ app/(application)/project/[id]/index.tsx | 2 + app/(application)/project/[id]/report.tsx | 128 +++++++++++++++++ components/project/headerProjectDetail.tsx | 59 +++++--- components/project/sectionReportProject.tsx | 55 ++++++++ components/task/headerTaskDetail.tsx | 62 ++++++--- components/task/sectionReportTask.tsx | 53 +++++++ components/textExpandable.tsx | 83 +++++++++++ constants/Styles.ts | 8 +- lib/api.ts | 10 ++ lib/projectUpdate.ts | 1 + lib/taskUpdate.ts | 1 + 13 files changed, 552 insertions(+), 49 deletions(-) create mode 100644 app/(application)/division/[id]/(fitur-division)/task/[detail]/report.tsx create mode 100644 app/(application)/project/[id]/report.tsx create mode 100644 components/project/sectionReportProject.tsx create mode 100644 components/task/sectionReportTask.tsx create mode 100644 components/textExpandable.tsx diff --git a/app/(application)/division/[id]/(fitur-division)/task/[detail]/index.tsx b/app/(application)/division/[id]/(fitur-division)/task/[detail]/index.tsx index 344b118..b7edf09 100644 --- a/app/(application)/division/[id]/(fitur-division)/task/[detail]/index.tsx +++ b/app/(application)/division/[id]/(fitur-division)/task/[detail]/index.tsx @@ -5,6 +5,7 @@ import HeaderRightTaskDetail from "@/components/task/headerTaskDetail"; import SectionFileTask from "@/components/task/sectionFileTask"; import SectionLinkTask from "@/components/task/sectionLinkTask"; import SectionMemberTask from "@/components/task/sectionMemberTask"; +import SectionReportTask from "@/components/task/sectionReportTask"; import SectionTanggalTugasTask from "@/components/task/sectionTanggalTugasTask"; import Styles from "@/constants/Styles"; import { apiGetTaskOne } from "@/lib/api"; @@ -89,10 +90,11 @@ export default function DetailTaskDivision() { data?.reason != null && data?.reason != "" && } - - - - + + + + + diff --git a/app/(application)/division/[id]/(fitur-division)/task/[detail]/report.tsx b/app/(application)/division/[id]/(fitur-division)/task/[detail]/report.tsx new file mode 100644 index 0000000..f9a5239 --- /dev/null +++ b/app/(application)/division/[id]/(fitur-division)/task/[detail]/report.tsx @@ -0,0 +1,129 @@ +import ButtonBackHeader from "@/components/buttonBackHeader"; +import ButtonSaveHeader from "@/components/buttonSaveHeader"; +import { InputForm } from "@/components/inputForm"; +import Styles from "@/constants/Styles"; +import { apiGetTaskOne, apiReportTask } from "@/lib/api"; +import { setUpdateTask } from "@/lib/taskUpdate"; +import { useAuthSession } from "@/providers/AuthProvider"; +import { router, Stack, useLocalSearchParams } from "expo-router"; +import { useEffect, useState } from "react"; +import { SafeAreaView, ScrollView, View } from "react-native"; +import Toast from "react-native-toast-message"; +import { useDispatch, useSelector } from "react-redux"; + +export default function TaskDivisionReport() { + const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>(); + const { token, decryptToken } = useAuthSession(); + const [laporan, setLaporan] = useState(""); + const [error, setError] = useState(false); + const [disable, setDisable] = useState(false); + const dispatch = useDispatch(); + const update = useSelector((state: any) => state.taskUpdate); + const [loading, setLoading] = useState(false) + + async function handleLoad() { + try { + const hasil = await decryptToken(String(token?.current)); + const response = await apiGetTaskOne({ + user: hasil, + cat: "data", + id: detail, + }); + setLaporan(response.data.report); + } catch (error) { + console.error(error); + } + } + + useEffect(() => { + handleLoad(); + }, []); + + function onValidation(val: string) { + setLaporan(val); + if (val == "" || val == "null") { + setError(true); + } else { + setError(false); + } + } + + function checkAll() { + if (laporan == "" || laporan == "null" || laporan == undefined || laporan == null || error) { + setDisable(true); + } else { + setDisable(false); + } + } + + useEffect(() => { + checkAll(); + }, [laporan, error]); + + async function handleUpdate() { + try { + setLoading(true) + const hasil = await decryptToken(String(token?.current)); + const response = await apiReportTask( + { + report: laporan, + user: hasil, + }, + detail + ); + if (response.success) { + dispatch(setUpdateTask({ ...update, report: !update.report })); + Toast.show({ type: 'small', text1: 'Berhasil mengubah data', }) + router.back(); + } else { + Toast.show({ type: 'small', text1: response.message, }) + } + } catch (error) { + console.error(error); + Toast.show({ type: 'small', text1: 'Terjadi kesalahan', }) + } finally { + setLoading(false) + } + } + + return ( + + ( + { + router.back(); + }} + /> + ), + headerTitle: "Laporan Kegiatan", + headerTitleAlign: "center", + headerRight: () => ( + { handleUpdate() }} + /> + ), + }} + /> + + + { onValidation(val) }} + error={error} + errorText="Laporan kegiatan harus diisi" + multiline + /> + + + + ); +} diff --git a/app/(application)/project/[id]/index.tsx b/app/(application)/project/[id]/index.tsx index 258f2fb..84c1db2 100644 --- a/app/(application)/project/[id]/index.tsx +++ b/app/(application)/project/[id]/index.tsx @@ -3,6 +3,7 @@ import HeaderRightProjectDetail from "@/components/project/headerProjectDetail"; import SectionFile from "@/components/project/sectionFile"; import SectionLink from "@/components/project/sectionLink"; import SectionMember from "@/components/project/sectionMember"; +import SectionReportProject from "@/components/project/sectionReportProject"; import SectionTanggalTugasProject from "@/components/project/sectionTanggalTugas"; import SectionCancel from "@/components/sectionCancel"; import SectionProgress from "@/components/sectionProgress"; @@ -112,6 +113,7 @@ export default function DetailProject() { data?.reason != null && data?.reason != "" && } + diff --git a/app/(application)/project/[id]/report.tsx b/app/(application)/project/[id]/report.tsx new file mode 100644 index 0000000..8455332 --- /dev/null +++ b/app/(application)/project/[id]/report.tsx @@ -0,0 +1,128 @@ +import ButtonBackHeader from "@/components/buttonBackHeader"; +import ButtonSaveHeader from "@/components/buttonSaveHeader"; +import { InputForm } from "@/components/inputForm"; +import Styles from "@/constants/Styles"; +import { apiGetProjectOne, apiReportProject } from "@/lib/api"; +import { setUpdateProject } from "@/lib/projectUpdate"; +import { useAuthSession } from "@/providers/AuthProvider"; +import { router, Stack, useLocalSearchParams } from "expo-router"; +import { useEffect, useState } from "react"; +import { SafeAreaView, ScrollView, View } from "react-native"; +import Toast from "react-native-toast-message"; +import { useDispatch, useSelector } from "react-redux"; + +export default function ReportProject() { + const { token, decryptToken } = useAuthSession(); + const { id } = useLocalSearchParams<{ id: string }>(); + const dispatch = useDispatch() + const update = useSelector((state: any) => state.projectUpdate) + const [laporan, setLaporan] = useState(""); + const [error, setError] = useState(false); + const [disable, setDisable] = useState(false); + const [loading, setLoading] = useState(false) + + async function handleLoad() { + try { + const hasil = await decryptToken(String(token?.current)); + const response = await apiGetProjectOne({ + user: hasil, + cat: "data", + id: id, + }); + setLaporan(response.data.report); + } catch (error) { + console.error(error); + } + } + + useEffect(() => { + handleLoad(); + }, []); + + function onValidation(val: string) { + setLaporan(val) + if (val == "" || val == "null") { + setError(true) + } else { + setError(false) + } + } + + function checkAll() { + if (laporan == "" || laporan == "null" || laporan == null || laporan == undefined || error) { + setDisable(true) + } else { + setDisable(false) + } + } + + useEffect(() => { + checkAll() + }, [laporan, error]); + + async function handleUpdate() { + try { + setLoading(true) + const hasil = await decryptToken(String(token?.current)); + const response = await apiReportProject({ + report: laporan, + user: hasil, + }, id); + if (response.success) { + dispatch(setUpdateProject({ ...update, report: !update.report })) + Toast.show({ type: 'small', text1: 'Berhasil mengubah data', }) + router.back(); + } else { + Toast.show({ type: 'small', text1: response.message, }) + } + } catch (error) { + console.error(error); + Toast.show({ type: 'small', text1: 'Terjadi kesalahan', }) + } finally { + setLoading(false) + } + } + + + + return ( + + ( + { + router.back(); + }} + /> + ), + headerTitle: "Laporan Kegiatan", + headerTitleAlign: "center", + headerRight: () => ( + { handleUpdate() }} + /> + ), + }} + /> + + + { onValidation(val) }} + error={error} + errorText="Judul Kegiatan harus diisi" + multiline + /> + + + + ); +} diff --git a/components/project/headerProjectDetail.tsx b/components/project/headerProjectDetail.tsx index 57b0c7a..d74aa21 100644 --- a/components/project/headerProjectDetail.tsx +++ b/components/project/headerProjectDetail.tsx @@ -67,7 +67,7 @@ export default function HeaderRightProjectDetail({ id, status }: Props) { return ( <> { setVisible(true) }} /> - + } @@ -102,29 +102,46 @@ export default function HeaderRightProjectDetail({ id, status }: Props) { disabled={status == 3} /> + + } + title="Laporan Kegiatan" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`/project/${id}/report`) + }} + disabled={status == 3} + /> + { + entityUser.role != "user" && entityUser.role != "coadmin" && + <> + } + title="Tambah Anggota" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`/project/${id}/add-member`) + }} + disabled={status == 3} + /> + } + title="Edit" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`/project/${id}/edit`) + }} + disabled={status == 3} + /> + + } + { entityUser.role != "user" && entityUser.role != "coadmin" && - } - title="Tambah Anggota" - onPress={() => { - if (status == 3) return - setVisible(false) - router.push(`/project/${id}/add-member`) - }} - disabled={status == 3} - /> - } - title="Edit" - onPress={() => { - if (status == 3) return - setVisible(false) - router.push(`/project/${id}/edit`) - }} - disabled={status == 3} - /> { status == 3 ? diff --git a/components/project/sectionReportProject.tsx b/components/project/sectionReportProject.tsx new file mode 100644 index 0000000..18e7b82 --- /dev/null +++ b/components/project/sectionReportProject.tsx @@ -0,0 +1,55 @@ +import Styles from "@/constants/Styles"; +import { apiGetProjectOne } from "@/lib/api"; +import { useAuthSession } from "@/providers/AuthProvider"; +import { useLocalSearchParams } from "expo-router"; +import { useEffect, useState } from "react"; +import { View } from "react-native"; +import { useSelector } from "react-redux"; +import Text from "../Text"; +import TextExpandable from "../textExpandable"; + +export default function SectionReportProject({ refreshing }: { refreshing?: boolean }) { + const update = useSelector((state: any) => state.projectUpdate) + const { token, decryptToken } = useAuthSession(); + const { id } = useLocalSearchParams<{ id: string }>(); + const [data, setData] = useState(""); + + async function handleLoad() { + try { + const hasil = await decryptToken(String(token?.current)); + const response = await apiGetProjectOne({ + user: hasil, + cat: "data", + id: id, + }); + setData(response.data.report); + } catch (error) { + console.error(error); + } + } + + useEffect(() => { + handleLoad(); + }, [update.report]); + + useEffect(() => { + if (refreshing) + handleLoad(); + }, [refreshing]); + + return ( + <> + { + data != "" && data != null && + + + Laporan Kegiatan + + + + + + } + + ); +} diff --git a/components/task/headerTaskDetail.tsx b/components/task/headerTaskDetail.tsx index 816738f..adfc86b 100644 --- a/components/task/headerTaskDetail.tsx +++ b/components/task/headerTaskDetail.tsx @@ -101,7 +101,7 @@ export default function HeaderRightTaskDetail({ id, division, status }: Props) { : { setVisible(true) }} /> } - + } @@ -137,31 +137,49 @@ export default function HeaderRightTaskDetail({ id, division, status }: Props) { disabled={status == 3} /> + + } + title="Laporan Kegiatan" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`./${id}/report`) + }} + disabled={status == 3} + /> + { + ((entityUser.role != "user" && entityUser.role != "coadmin") || isAdminDivision) + && + <> + } + title="Tambah Anggota" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`./${id}/add-member`) + }} + disabled={status == 3} + /> + } + title="Edit" + onPress={() => { + if (status == 3) return + setVisible(false) + router.push(`./${id}/edit`) + }} + disabled={status == 3} + /> + + } + { ((entityUser.role != "user" && entityUser.role != "coadmin") || isAdminDivision) && - } - title="Tambah Anggota" - onPress={() => { - if (status == 3) return - setVisible(false) - router.push(`./${id}/add-member`) - }} - disabled={status == 3} - /> - } - title="Edit" - onPress={() => { - if (status == 3) return - setVisible(false) - router.push(`./${id}/edit`) - }} - disabled={status == 3} - /> { status == 3 ? @@ -190,7 +208,7 @@ export default function HeaderRightTaskDetail({ id, division, status }: Props) { } } - + state.taskUpdate) + const { token, decryptToken } = useAuthSession() + const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>(); + const [data, setData] = useState('') + + async function handleLoad() { + try { + const hasil = await decryptToken(String(token?.current)) + const response = await apiGetTaskOne({ id: detail, user: hasil, cat: 'data' }) + setData(response.data.report) + } catch (error) { + console.error(error) + } + } + + useEffect(() => { + handleLoad() + }, [update.report]) + + useEffect(() => { + if (refreshing) + handleLoad(); + }, [refreshing]); + + + return ( + <> + { + data != "" && data != null && + + + Laporan Kegiatan + + + + + + } + + ) +} \ No newline at end of file diff --git a/components/textExpandable.tsx b/components/textExpandable.tsx new file mode 100644 index 0000000..13e4413 --- /dev/null +++ b/components/textExpandable.tsx @@ -0,0 +1,83 @@ +import Styles from "@/constants/Styles"; +import { useRef, useState, useEffect } from "react"; +import { Animated, Pressable, View } from "react-native"; +import Text from "./Text"; + +export default function TextExpandable({ content, maxLines }: { content: string, maxLines: number }) { + const [isExpanded, setIsExpanded] = useState(false); + const [shouldShowMore, setShouldShowMore] = useState(false); + const [collapsedHeight, setCollapsedHeight] = useState(0); + const [fullHeight, setFullHeight] = useState(0); + const animatedHeight = useRef(new Animated.Value(0)).current; + + const measureCollapsed = (e: any) => { + if (collapsedHeight === 0) { + setCollapsedHeight(e.nativeEvent.layout.height); + animatedHeight.setValue(e.nativeEvent.layout.height); + } + }; + + const measureFull = (e: any) => { + if (fullHeight === 0) { + setFullHeight(e.nativeEvent.layout.height); + } + }; + + // Cek apakah memang perlu "View More" + useEffect(() => { + if (collapsedHeight > 0 && fullHeight > 0) { + setShouldShowMore(fullHeight > collapsedHeight + 1); // +1 untuk toleransi float + } + }, [collapsedHeight, fullHeight]); + + const toggleExpand = () => { + Animated.timing(animatedHeight, { + toValue: isExpanded ? collapsedHeight : fullHeight, + duration: 300, + useNativeDriver: false, + }).start(); + setIsExpanded(!isExpanded); + }; + + return ( + + {/* Hidden full text for measurement */} + + + {content} + + + + {/* Collapsed text for measurement */} + + + {content} + + + + {/* Animated visible text */} + + + {content} + + + + {shouldShowMore && ( + + + {isExpanded ? 'View Less' : 'View More'} + + + )} + + ); +}; diff --git a/constants/Styles.ts b/constants/Styles.ts index 4af2ba9..4b22a9d 100644 --- a/constants/Styles.ts +++ b/constants/Styles.ts @@ -45,8 +45,7 @@ const Styles = StyleSheet.create({ fontWeight: 'bold', }, textLink: { - lineHeight: 30, - fontSize: 16, + fontSize: 14, color: '#0a7ea4', }, textInformation: { @@ -593,6 +592,11 @@ const Styles = StyleSheet.create({ bottom: 5, right: 5, position: 'absolute' + }, + hidden: { + position: 'absolute', + opacity: 0, + zIndex: -1, } }) diff --git a/lib/api.ts b/lib/api.ts index aa71619..40958bb 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -274,6 +274,11 @@ export const apiEditProject = async (data: { name: string, user: string }, id: s return response.data; }; +export const apiReportProject = async (data: { report: string, user: string }, id: string) => { + const response = await api.put(`/mobile/project/${id}/lainnya`, data) + return response.data; +}; + export const apiCreateProjectTask = async ({ data, id }: { data: { name: string, dateStart: string, user: string, dateEnd: string }, id: string }) => { const response = await api.post(`/mobile/project/${id}`, data) return response.data; @@ -584,6 +589,11 @@ export const apiEditTask = async (data: { title: string, user: string }, id: str return response.data; }; +export const apiReportTask = async (data: { report: string, user: string }, id: string) => { + const response = await api.put(`/mobile/task/${id}/lainnya`, data) + return response.data; +}; + export const apiCancelTask = async (data: { user: string, reason: string }, id: string) => { const response = await api.delete(`mobile/task/${id}`, { data }) return response.data diff --git a/lib/projectUpdate.ts b/lib/projectUpdate.ts index 8174441..3453957 100644 --- a/lib/projectUpdate.ts +++ b/lib/projectUpdate.ts @@ -9,6 +9,7 @@ const projectUpdate = createSlice({ file: false, member: false, link: false, + report: false, }, reducers: { setUpdateProject: (state, action) => { diff --git a/lib/taskUpdate.ts b/lib/taskUpdate.ts index 2e7fbf0..8f68e53 100644 --- a/lib/taskUpdate.ts +++ b/lib/taskUpdate.ts @@ -9,6 +9,7 @@ const taskUpdate = createSlice({ file: false, member: false, link: false, + report: false, }, reducers: { setUpdateTask: (state, action) => { From 2e5698b566bc27c947117ac698486862929d7912 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Fri, 15 Aug 2025 11:53:46 +0800 Subject: [PATCH 2/5] fix: tampilan Deskripsi: - tinggi modal No Issues --- components/project/headerProjectDetail.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/project/headerProjectDetail.tsx b/components/project/headerProjectDetail.tsx index d74aa21..4459635 100644 --- a/components/project/headerProjectDetail.tsx +++ b/components/project/headerProjectDetail.tsx @@ -67,7 +67,7 @@ export default function HeaderRightProjectDetail({ id, status }: Props) { return ( <> { setVisible(true) }} /> - + } From 0956dea8466f7ed233a9f7c7c7c9c0c0beaf567b Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Fri, 15 Aug 2025 16:25:48 +0800 Subject: [PATCH 3/5] upd: tampilan Deskripsi: - header menu detail project - header menu detail tugas divisi No Issues --- components/project/headerProjectDetail.tsx | 2 +- components/task/headerTaskDetail.tsx | 2 +- lib/api.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/project/headerProjectDetail.tsx b/components/project/headerProjectDetail.tsx index 4459635..d19e629 100644 --- a/components/project/headerProjectDetail.tsx +++ b/components/project/headerProjectDetail.tsx @@ -105,7 +105,7 @@ export default function HeaderRightProjectDetail({ id, status }: Props) { } - title="Laporan Kegiatan" + title="Laporan" onPress={() => { if (status == 3) return setVisible(false) diff --git a/components/task/headerTaskDetail.tsx b/components/task/headerTaskDetail.tsx index adfc86b..392c6da 100644 --- a/components/task/headerTaskDetail.tsx +++ b/components/task/headerTaskDetail.tsx @@ -140,7 +140,7 @@ export default function HeaderRightTaskDetail({ id, division, status }: Props) { } - title="Laporan Kegiatan" + title="Laporan" onPress={() => { if (status == 3) return setVisible(false) diff --git a/lib/api.ts b/lib/api.ts index 40958bb..51d77b4 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -3,7 +3,7 @@ import axios from 'axios'; const api = axios.create({ // baseURL: 'http://10.0.2.2:3000/api', // baseURL: 'https://stg-darmasaba.wibudev.com/api', - baseURL: 'http://192.168.1.110:3000/api', + baseURL: 'http://192.168.154.198:3000/api', }); export const apiCheckPhoneLogin = async (body: { phone: string }) => { From 7810eb16860cc61a801bbdf02fa0a10eb4e07349 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Fri, 15 Aug 2025 17:20:23 +0800 Subject: [PATCH 4/5] upd: pake env Deskripsi: - ganti app.json menjadi app.config.js agar bisa pake env - membuat env - ganti url pake env > api url, storage url, firebase database url, otp url No Issues --- .gitignore | 3 + app.config.js | 72 ++++++++++++++++++ app.json => app.json.bak | 0 bun.lockb | Bin 479848 -> 480264 bytes components/project/sectionFile.tsx | 6 -- constants/Colors.ts | 5 -- constants/ConstEnv.ts | 5 ++ ios/mobiledarmasaba.xcodeproj/project.pbxproj | 12 ++- lib/api.ts | 6 +- package.json | 1 + 10 files changed, 93 insertions(+), 17 deletions(-) create mode 100644 app.config.js rename app.json => app.json.bak (100%) create mode 100644 constants/ConstEnv.ts diff --git a/.gitignore b/.gitignore index e9af40e..733c661 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,9 @@ yarn-error.* # local env files .env*.local +#env +.env + # typescript *.tsbuildinfo diff --git a/app.config.js b/app.config.js new file mode 100644 index 0000000..fae5d7b --- /dev/null +++ b/app.config.js @@ -0,0 +1,72 @@ +import 'dotenv/config'; + +export default { + expo: { + name: "mobile-darmasaba", + slug: "mobile-darmasaba", + version: "1.0.0", + jsEngine: "jsc", + orientation: "portrait", + icon: "./assets/images/icon.png", + scheme: "myapp", + userInterfaceStyle: "automatic", + newArchEnabled: false, + ios: { + supportsTablet: true, + bundleIdentifier: "mobiledarmasaba.app", + infoPlist: { + ITSAppUsesNonExemptEncryption: false + }, + googleServicesFile: "./ios/mobiledarmasaba/GoogleService-Info.plist" + }, + android: { + package: "mobiledarmasaba.app", + adaptiveIcon: { + foregroundImage: "./assets/images/splash-icon.png", + backgroundColor: "#ffffff" + }, + googleServicesFile: "./google-services.json" + }, + web: { + bundler: "metro", + output: "static", + favicon: "./assets/images/favicon.png" + }, + plugins: [ + "expo-router", + [ + "expo-splash-screen", + { + image: "./assets/images/splash-icon.png", + imageWidth: 200, + resizeMode: "contain", + backgroundColor: "#ffffff" + } + ], + "expo-font", + "expo-image-picker", + "expo-web-browser", + [ + "@react-native-firebase/app", + { + ios: { + googleServicesFile: "./ios/mobiledarmasaba/GoogleService-Info.plist" + } + } + ] + ], + experiments: { + typedRoutes: true + }, + extra: { + router: {}, + eas: { + projectId: "cfe34fb8-da8c-4004-b5c6-29d07df75cf2" + }, + URL_API: process.env.URL_API, + URL_OTP: process.env.URL_OTP, + URL_STORAGE : process.env.URL_STORAGE, + URL_FIREBASE_DB : process.env.URL_FIREBASE_DB + } + } +}; diff --git a/app.json b/app.json.bak similarity index 100% rename from app.json rename to app.json.bak diff --git a/bun.lockb b/bun.lockb index 3bae3c90aabe4b56d7feaa9bddb7d8115ff2e6c5..c827a4d565a6afeada3d24a4aaa2d7aa8d20a453 100755 GIT binary patch delta 44857 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 diff --git a/components/project/sectionFile.tsx b/components/project/sectionFile.tsx index 524b560..77311f4 100644 --- a/components/project/sectionFile.tsx +++ b/components/project/sectionFile.tsx @@ -90,12 +90,6 @@ export default function SectionFile({ status, member, refreshing }: { status: nu } } - // async function download() { - // const destination = new Directory(Paths.document, 'pdfs'); - // const filename = "dummy.pdf"; - // const result = await File.downloadFileAsync('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', destination); - // } - const openFile = () => { setModal(false) diff --git a/constants/Colors.ts b/constants/Colors.ts index 54c7695..be9eec1 100644 --- a/constants/Colors.ts +++ b/constants/Colors.ts @@ -1,8 +1,3 @@ -/** - * Below are the colors that are used in the app. The colors are defined in the light and dark mode. - * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc. - */ - const tintColorLight = '#19345E'; const tintColorDark = '#fff'; diff --git a/constants/ConstEnv.ts b/constants/ConstEnv.ts new file mode 100644 index 0000000..65de1b0 --- /dev/null +++ b/constants/ConstEnv.ts @@ -0,0 +1,5 @@ +import Constants from 'expo-constants'; + +export const ConstEnv = { + url_storage : Constants?.expoConfig?.extra?.URL_STORAGE +} \ No newline at end of file diff --git a/ios/mobiledarmasaba.xcodeproj/project.pbxproj b/ios/mobiledarmasaba.xcodeproj/project.pbxproj index 9ce7135..0d873ad 100644 --- a/ios/mobiledarmasaba.xcodeproj/project.pbxproj +++ b/ios/mobiledarmasaba.xcodeproj/project.pbxproj @@ -252,8 +252,6 @@ "$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", ); name = "[CP-User] [RNFB] Core Configuration"; - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##########################################################################\n##########################################################################\n#\n# NOTE THAT IF YOU CHANGE THIS FILE YOU MUST RUN pod install AFTERWARDS\n#\n# This file is installed as an Xcode build script in the project file\n# by cocoapods, and you will not see your changes until you pod install\n#\n##########################################################################\n##########################################################################\n\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n echo \"info: setting plist entry '$1' of type '$2' in file '$4'\"\n ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info: '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n else\n echo \"\"\n fi;\n}\n\nfunction jsonBoolToYesNo () {\n if [[ $1 == \"false\" ]]; then\n echo \"NO\"\n elif [[ $1 == \"true\" ]]; then\n echo \"YES\"\n else echo \"NO\"\n fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n echo \"info: ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | /usr/bin/head -n 1)\n if [[ ${_SEARCH_RESULT} ]]; then\n echo \"info: ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n break;\n fi;\n _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n _RN_ROOT_EXISTS=$(ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n if ! python3 --version >/dev/null 2>&1; then echo \"python3 not found, firebase.json file processing error.\" && exit 1; fi\n _JSON_OUTPUT_BASE64=$(python3 -c 'import json,sys,base64;print(base64.b64encode(bytes(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"', '\"'rb'\"').read())['${_JSON_ROOT}']), '\"'utf-8'\"')).decode())' || echo \"e30=\")\n fi\n\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n # config.app_data_collection_default_enabled\n _APP_DATA_COLLECTION_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_data_collection_default_enabled\")\n if [[ $_APP_DATA_COLLECTION_ENABLED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseDataCollectionDefaultEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_DATA_COLLECTION_ENABLED\")\")\n fi\n\n # config.analytics_auto_collection_enabled\n _ANALYTICS_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_auto_collection_enabled\")\n if [[ $_ANALYTICS_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_COLLECTION\")\")\n fi\n\n # config.analytics_collection_deactivated\n _ANALYTICS_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_collection_deactivated\")\n if [[ $_ANALYTICS_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_DEACTIVATED\")\")\n fi\n\n # config.analytics_idfv_collection_enabled\n _ANALYTICS_IDFV_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_idfv_collection_enabled\")\n if [[ $_ANALYTICS_IDFV_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_IDFV_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_IDFV_COLLECTION\")\")\n fi\n\n # config.analytics_default_allow_analytics_storage\n _ANALYTICS_STORAGE=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_analytics_storage\")\n if [[ $_ANALYTICS_STORAGE ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_ANALYTICS_STORAGE\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_STORAGE\")\")\n fi\n\n # config.analytics_default_allow_ad_storage\n _ANALYTICS_AD_STORAGE=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_storage\")\n if [[ $_ANALYTICS_AD_STORAGE ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_STORAGE\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AD_STORAGE\")\")\n fi\n\n # config.analytics_default_allow_ad_user_data\n _ANALYTICS_AD_USER_DATA=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_user_data\")\n if [[ $_ANALYTICS_AD_USER_DATA ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_USER_DATA\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AD_USER_DATA\")\")\n fi\n\n # config.analytics_default_allow_ad_personalization_signals\n _ANALYTICS_PERSONALIZATION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_personalization_signals\")\n if [[ $_ANALYTICS_PERSONALIZATION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_PERSONALIZATION\")\")\n fi\n\n # config.analytics_registration_with_ad_network_enabled\n _ANALYTICS_REGISTRATION_WITH_AD_NETWORK=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_registration_with_ad_network_enabled\")\n if [[ $_ANALYTICS_REGISTRATION_WITH_AD_NETWORK ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_REGISTRATION_WITH_AD_NETWORK\")\")\n fi\n\n # config.google_analytics_automatic_screen_reporting_enabled\n _ANALYTICS_AUTO_SCREEN_REPORTING=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_automatic_screen_reporting_enabled\")\n if [[ $_ANALYTICS_AUTO_SCREEN_REPORTING ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAutomaticScreenReportingEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_SCREEN_REPORTING\")\")\n fi\n\n # config.perf_auto_collection_enabled\n _PERF_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_auto_collection_enabled\")\n if [[ $_PERF_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_enabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_AUTO_COLLECTION\")\")\n fi\n\n # config.perf_collection_deactivated\n _PERF_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_collection_deactivated\")\n if [[ $_PERF_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_deactivated\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_DEACTIVATED\")\")\n fi\n\n # config.messaging_auto_init_enabled\n _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n if [[ $_MESSAGING_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n fi\n\n # config.in_app_messaging_auto_colllection_enabled\n _FIAM_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"in_app_messaging_auto_collection_enabled\")\n if [[ $_FIAM_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseInAppMessagingAutomaticDataCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_FIAM_AUTO_INIT\")\")\n fi\n\n # config.app_check_token_auto_refresh\n _APP_CHECK_TOKEN_AUTO_REFRESH=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_check_token_auto_refresh\")\n if [[ $_APP_CHECK_TOKEN_AUTO_REFRESH ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAppCheckTokenAutoRefreshEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_CHECK_TOKEN_AUTO_REFRESH\")\")\n fi\n\n # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes useful\n _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n echo \"Disabled Crashlytics auto disabler.\" # do nothing\n else\n _PLIST_ENTRY_KEYS+=(\"FirebaseCrashlyticsCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"NO\")\n fi\nelse\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n echo \"warning: A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n echo \" -> $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in \"${_TARGET_PLIST}\" \"${_DSYM_PLIST}\" ; do\n if [[ -f \"${plist}\" ]]; then\n\n # paths with spaces break the call to setPlistValue. temporarily modify\n # the shell internal field separator variable (IFS), which normally\n # includes spaces, to consist only of line breaks\n oldifs=$IFS\n IFS=\"\n\"\n\n for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n done\n\n # restore the original internal field separator value\n IFS=$oldifs\n else\n echo \"warning: A Info.plist build output file was not found (${plist})\"\n fi\ndone\n\necho \"info: <- RNFB build script finished\"\n"; @@ -489,7 +487,10 @@ LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -544,7 +545,10 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = false; diff --git a/lib/api.ts b/lib/api.ts index 51d77b4..8b1f509 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -1,9 +1,11 @@ import axios from 'axios'; +import Constants from 'expo-constants'; const api = axios.create({ // baseURL: 'http://10.0.2.2:3000/api', // baseURL: 'https://stg-darmasaba.wibudev.com/api', - baseURL: 'http://192.168.154.198:3000/api', + // baseURL: 'http://192.168.154.198:3000/api', + baseURL: Constants?.expoConfig?.extra?.URL_API }); export const apiCheckPhoneLogin = async (body: { phone: string }) => { @@ -12,7 +14,7 @@ export const apiCheckPhoneLogin = async (body: { phone: string }) => { } export const apiSendOtp = async (body: { phone: string, otp: number }) => { - const res = await axios.get(`https://wa.wibudev.com/code?nom=${body.phone}&text=*DARMASABA*%0A%0A + const res = await axios.get(`${Constants.expoConfig?.extra?.URL_OTP}/code?nom=${body.phone}&text=*DARMASABA*%0A%0A JANGAN BERIKAN KODE RAHASIA ini kepada siapa pun TERMASUK PIHAK DARMASABA. Masukkan otentikasi: *${encodeURIComponent(body.otp)}*`) return res.status } diff --git a/package.json b/package.json index 61d2a97..815c340 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "crypto-es": "^2.1.0", "crypto-js": "^3.1.9-1", "dayjs": "^1.11.13", + "dotenv": "^17.2.1", "expo": "^53.0.9", "expo-blur": "~14.1.4", "expo-clipboard": "^7.1.4", From 263875ae55ad1263c7495504a8e1baef883acf58 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Tue, 19 Aug 2025 17:39:27 +0800 Subject: [PATCH 5/5] upd: fitur tambahan project Deskripsi: - tampilan list detail waktu task project - integrasi api mobile list detail - tampilan tambah detail task project > blm selesai No Issues --- app/(application)/project/[id]/add-task.tsx | 11 +- app/(application)/project/create/task.tsx | 2 +- components/modalFloat.tsx | 2 +- .../project/modalListDetailTugasProject.tsx | 116 ++++++++++++++++++ components/project/sectionTanggalTugas.tsx | 26 ++++ constants/Styles.ts | 6 + lib/api.ts | 4 +- 7 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 components/project/modalListDetailTugasProject.tsx diff --git a/app/(application)/project/[id]/add-task.tsx b/app/(application)/project/[id]/add-task.tsx index 640817a..78e8f3c 100644 --- a/app/(application)/project/[id]/add-task.tsx +++ b/app/(application)/project/[id]/add-task.tsx @@ -6,14 +6,16 @@ import Styles from "@/constants/Styles"; import { apiCreateProjectTask } from "@/lib/api"; import { setUpdateProject } from "@/lib/projectUpdate"; import { useAuthSession } from "@/providers/AuthProvider"; -import 'intl'; -import 'intl/locale-data/jsonp/id'; +import { useHeaderHeight } from '@react-navigation/elements'; import dayjs from "dayjs"; import { router, Stack, useLocalSearchParams } from "expo-router"; +import 'intl'; +import 'intl/locale-data/jsonp/id'; import { useEffect, useState } from "react"; import { KeyboardAvoidingView, Platform, + Pressable, SafeAreaView, ScrollView, View @@ -23,7 +25,6 @@ import DateTimePicker, { DateType } from "react-native-ui-datepicker"; import { useDispatch, useSelector } from "react-redux"; -import { useHeaderHeight } from '@react-navigation/elements'; export default function ProjectAddTask() { const headerHeight = useHeaderHeight(); @@ -162,6 +163,10 @@ export default function ProjectAddTask() { { (error.endDate || error.startDate) && Tanggal tidak boleh kosong } + {/* TODO */} + + Detail + void title?: string children: React.ReactNode - onSubmit: () => void + onSubmit?: () => void disableSubmit?: boolean buttonHide?: boolean } diff --git a/components/project/modalListDetailTugasProject.tsx b/components/project/modalListDetailTugasProject.tsx new file mode 100644 index 0000000..8c665c5 --- /dev/null +++ b/components/project/modalListDetailTugasProject.tsx @@ -0,0 +1,116 @@ +import Styles from "@/constants/Styles"; +import { apiGetProjectTask } from "@/lib/api"; +import { useAuthSession } from "@/providers/AuthProvider"; +import { useEffect, useState } from "react"; +import { Dimensions, View, VirtualizedList } from "react-native"; +import { InputDate } from "../inputDate"; +import ModalFloat from "../modalFloat"; +import Skeleton from "../skeleton"; +import Text from "../Text"; + +interface Props { + id: string; + date: string; + timeStart: string; + timeEnd: string; +} + +export default function ModalListDetailTugasProject({ isVisible, setVisible, idTask }: { isVisible: boolean, setVisible: (value: boolean) => void, idTask: string }) { + const [data, setData] = useState([]) + const [loading, setLoading] = useState(false) + const { token, decryptToken } = useAuthSession() + const arrSkeleton = Array.from({ length: 3 }, (_, index) => index) + const tinggiScreen = Dimensions.get("window").height; + const tinggiFix = tinggiScreen * 70 / 100; + + + + async function getData() { + try { + setLoading(true) + const hasil = await decryptToken(String(token?.current)); + const res = await apiGetProjectTask({ user: hasil, id: idTask, cat: "detailTask" }) + setData(res.data) + } catch (error) { + console.error(error) + } finally { + setLoading(false) + } + } + + useEffect(() => { + if (isVisible) { + getData() + } + }, [isVisible, idTask]) + + const getItem = (_data: unknown, index: number): Props => ({ + id: data[index].id, + date: data[index].date, + timeStart: data[index].timeStart, + timeEnd: data[index].timeEnd, + }) + + return ( + + + { + loading ? + arrSkeleton.map((item: any, i: number) => { + return ( + + ) + }) + : + data.length > 0 ? + ( + data.length} + getItem={getItem} + renderItem={({ item, index }: { item: Props, index: number }) => { + return ( + + {item.date} + + + { }} + value={item.timeStart} + label="Waktu Awal" + placeholder="--:--" + /> + + + { }} + mode="time" + value={item.timeEnd} + label="Waktu Akhir" + placeholder="--:--" + disable + /> + + + + ) + }} + keyExtractor={(item, index) => String(index)} + showsVerticalScrollIndicator={false} + /> + ) + : + Tidak ada data + } + + + + ) +} \ No newline at end of file diff --git a/components/project/sectionTanggalTugas.tsx b/components/project/sectionTanggalTugas.tsx index ee3cb40..285b55e 100644 --- a/components/project/sectionTanggalTugas.tsx +++ b/components/project/sectionTanggalTugas.tsx @@ -15,6 +15,7 @@ import MenuItemRow from "../menuItemRow"; import ModalSelect from "../modalSelect"; import SkeletonTask from "../skeletonTask"; import Text from "../Text"; +import ModalListDetailTugasProject from "./modalListDetailTugasProject"; type Props = { id: string; @@ -33,6 +34,7 @@ export default function SectionTanggalTugasProject({ status, member, refreshing const [isModal, setModal] = useState(false); const [isSelect, setSelect] = useState(false); const { token, decryptToken } = useAuthSession(); + const [modalDetail, setModalDetail] = useState(false) const { id } = useLocalSearchParams<{ id: string }>(); const [data, setData] = useState([]); const [loading, setLoading] = useState(true) @@ -188,6 +190,24 @@ export default function SectionTanggalTugasProject({ status, member, refreshing }} /> + + } + title="Detail Waktu" + onPress={() => { + setModal(false); + setTimeout(() => { + setModalDetail(true) + }, 600) + }} + /> + + } title="Hapus Tugas" @@ -213,6 +233,12 @@ export default function SectionTanggalTugasProject({ status, member, refreshing open={isSelect} valChoose={String(tugas.status)} /> + + ); } diff --git a/constants/Styles.ts b/constants/Styles.ts index 4b22a9d..88b95a3 100644 --- a/constants/Styles.ts +++ b/constants/Styles.ts @@ -269,6 +269,12 @@ const Styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'center' }, + btnLainnya: { + alignSelf: 'flex-start', + backgroundColor: '#19345E', + paddingVertical: 5, + marginVertical: 5 + }, btnMenuRow: { width: '33%', alignItems: 'center' diff --git a/lib/api.ts b/lib/api.ts index 8b1f509..3a485df 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -301,8 +301,8 @@ export const apiDeleteProjectTask = async (data: { user: string, idProject: stri return response.data }; -export const apiGetProjectTask = async ({ user, id }: { user: string, id: string }) => { - const response = await api.get(`mobile/project/detail/${id}?user=${user}`); +export const apiGetProjectTask = async ({ user, id, cat }: { user: string, id: string, cat?: string }) => { + const response = await api.get(`mobile/project/detail/${id}?user=${user}${cat ? `&cat=${cat}` : ""}`); return response.data; };