upd: divisi
Deskripsi: - load data divisi - user role pada page list divisi - detail divisi - info divisi - tambah anggota divisi - hapus anggota divisi - update status admin divisi No Issues
This commit is contained in:
163
app/(application)/division/[id]/add-member.tsx
Normal file
163
app/(application)/division/[id]/add-member.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ImageUser from "@/components/imageNew";
|
||||
import ImageWithLabel from "@/components/imageWithLabel";
|
||||
import InputSearch from "@/components/inputSearch";
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiAddMemberDivision, apiGetDivisionOneDetail, apiGetProjectOne, apiGetUser } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { AntDesign } from "@expo/vector-icons";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native";
|
||||
|
||||
type Props = {
|
||||
idUser: string,
|
||||
name: string,
|
||||
img: string
|
||||
}
|
||||
|
||||
export default function AddMemberDivision() {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [dataOld, setDataOld] = useState<Props[]>([])
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const [idGroup, setIdGroup] = useState('')
|
||||
const [selectMember, setSelectMember] = useState<any[]>([])
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneDetail({ user: hasil, id })
|
||||
setDataOld(response.data.member)
|
||||
setIdGroup(response.data.division.idGroup)
|
||||
const responsemember = await apiGetUser({ user: hasil, active: "true", search: search, group: String(response.data.division.idGroup) })
|
||||
setData(responsemember.data.filter((i: any) => i.idUserRole != 'supadmin'))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLoadMember(search: string) {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetUser({ user: hasil, active: "true", search: search, group: String(idGroup) })
|
||||
setData(response.data.filter((i: any) => i.idUserRole != 'supadmin'))
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, []);
|
||||
|
||||
|
||||
function handleSearch(search: string) {
|
||||
setSearch(search)
|
||||
handleLoadMember(search)
|
||||
}
|
||||
|
||||
function onChoose(val: string, label: string, img?: string) {
|
||||
if (selectMember.some((i: any) => i.idUser == val)) {
|
||||
setSelectMember(selectMember.filter((i: any) => i.idUser != val))
|
||||
} else {
|
||||
setSelectMember([...selectMember, { idUser: val, name: label, img }])
|
||||
}
|
||||
}
|
||||
|
||||
async function handleAddMember() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiAddMemberDivision({ id: id, data: { user: hasil, member: selectMember } })
|
||||
if (response.success) {
|
||||
ToastAndroid.show('Berhasil menambahkan anggota', ToastAndroid.SHORT)
|
||||
router.replace(`/division/${id}/info`)
|
||||
} else {
|
||||
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ToastAndroid.show('Gagal menambahkan anggota', ToastAndroid.SHORT)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
headerTitle: 'Tambah Anggota',
|
||||
headerTitleAlign: 'center',
|
||||
headerRight: () => (
|
||||
<ButtonSaveHeader
|
||||
category="update"
|
||||
disable={selectMember.length > 0 ? false : true}
|
||||
onPress={() => {
|
||||
handleAddMember()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<View style={[Styles.p15]}>
|
||||
<InputSearch onChange={(val) => handleSearch(val)} value={search} />
|
||||
|
||||
{
|
||||
selectMember.length > 0
|
||||
?
|
||||
<View>
|
||||
<ScrollView horizontal style={[Styles.mb10, Styles.pv10]}>
|
||||
{
|
||||
selectMember.map((item: any, index: any) => (
|
||||
<ImageWithLabel
|
||||
key={index}
|
||||
label={item.name}
|
||||
src={item.img}
|
||||
onClick={() => onChoose(item.idUser, item.name, item.img)}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, Styles.pv05, { textAlign: 'center' }]}>Tidak ada member yang dipilih</Text>
|
||||
}
|
||||
<ScrollView>
|
||||
|
||||
{
|
||||
data.length > 0 ?
|
||||
data.map((item: any, index: any) => {
|
||||
const found = dataOld.some((i: any) => i.idUser == item.id)
|
||||
return (
|
||||
<Pressable
|
||||
key={index}
|
||||
style={[Styles.itemSelectModal]}
|
||||
onPress={() => {
|
||||
!found && onChoose(item.id, item.name, item.img)
|
||||
}}
|
||||
>
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} border />
|
||||
<View style={[Styles.ml10]}>
|
||||
<Text style={[Styles.textDefault]} numberOfLines={1} ellipsizeMode="tail">{item.name}</Text>
|
||||
{
|
||||
found && <Text style={[Styles.textInformation, Styles.cGray]}>sudah menjadi anggota</Text>
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
{
|
||||
selectMember.some((i: any) => i.idUser == item.id) && <AntDesign name="check" size={20} />
|
||||
}
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
)
|
||||
:
|
||||
<Text style={[Styles.textDefault, { textAlign: 'center' }]}>Tidak ada data</Text>
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
@@ -6,17 +6,51 @@ import HeaderRightDivisionDetail from "@/components/division/headerDivisionDetai
|
||||
import TaskDivisionDetail from "@/components/division/taskDivisionDetail"
|
||||
import CaraouselHome from "@/components/home/carouselHome"
|
||||
import Styles from "@/constants/Styles"
|
||||
import { apiGetDivisionOneDetail } from "@/lib/api"
|
||||
import { useAuthSession } from "@/providers/AuthProvider"
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router"
|
||||
import { useEffect, useState } from "react"
|
||||
import { SafeAreaView, ScrollView, View } from "react-native"
|
||||
|
||||
type Props = {
|
||||
id: string,
|
||||
idVillage: string,
|
||||
idGroup: string,
|
||||
name: string,
|
||||
desc: string,
|
||||
isActive: boolean,
|
||||
}
|
||||
|
||||
export default function DetailDivisionFitur() {
|
||||
const { id } = useLocalSearchParams()
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
setLoading(true)
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneDetail({ user: hasil, id })
|
||||
setData(response.data.division)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Stack.Screen
|
||||
options={{
|
||||
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||
headerTitle: 'Judul Divisi',
|
||||
headerTitle: loading ? 'Loading...' : data?.name,
|
||||
headerTitleAlign: 'center',
|
||||
headerRight: () => <HeaderRightDivisionDetail id={id} />,
|
||||
}}
|
||||
|
||||
@@ -3,31 +3,109 @@ import BorderBottomItem from "@/components/borderBottomItem"
|
||||
import ButtonBackHeader from "@/components/buttonBackHeader"
|
||||
import HeaderRightDivisionInfo from "@/components/division/headerDivisionInfo"
|
||||
import DrawerBottom from "@/components/drawerBottom"
|
||||
import ImageUser from "@/components/imageNew"
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus"
|
||||
import Styles from "@/constants/Styles"
|
||||
import { apiDeleteMemberDivision, apiGetDivisionOneDetail, apiUpdateStatusAdminDivision } from "@/lib/api"
|
||||
import { useAuthSession } from "@/providers/AuthProvider"
|
||||
import { Feather, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router"
|
||||
import { useState } from "react"
|
||||
import { Image, Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Pressable, SafeAreaView, ScrollView, Text, ToastAndroid, View } from "react-native"
|
||||
|
||||
type PropsDetail = {
|
||||
id: string,
|
||||
idVillage: string,
|
||||
idGroup: string,
|
||||
name: string,
|
||||
desc: string,
|
||||
isActive: boolean,
|
||||
}
|
||||
|
||||
type PropsMember = {
|
||||
id: string,
|
||||
isAdmin: boolean,
|
||||
isLeader: boolean,
|
||||
idUser: string,
|
||||
name: string,
|
||||
img: string
|
||||
}
|
||||
|
||||
export default function InformationDivision() {
|
||||
const { id } = useLocalSearchParams()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [isModal, setModal] = useState(false)
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const [dataDetail, setDataDetail] = useState<PropsDetail>()
|
||||
const [dataMember, setDataMember] = useState<PropsMember[]>([])
|
||||
const [refresh, setRefresh] = useState(false)
|
||||
const [dataMemberChoose, setDataMemberChoose] = useState({
|
||||
id: '',
|
||||
name: '',
|
||||
isAdmin: false
|
||||
})
|
||||
|
||||
function handleMemberOut() {
|
||||
AlertKonfirmasi({
|
||||
title: 'Konfirmasi',
|
||||
desc: 'Apakah anda yakin ingin mengeluarkan anggota?',
|
||||
onPress: () => {
|
||||
ToastAndroid.show('Berhasil mengeluarkan anggota', ToastAndroid.SHORT)
|
||||
setModal(false)
|
||||
}
|
||||
onPress: () => { memberOut() }
|
||||
})
|
||||
}
|
||||
|
||||
function handleMemberAdmin() {
|
||||
ToastAndroid.show('Berhasil memberhentikan admin', ToastAndroid.SHORT)
|
||||
setModal(false)
|
||||
async function memberOut() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiDeleteMemberDivision({ user: hasil, id: dataMemberChoose.id }, id)
|
||||
if (response.success) {
|
||||
setRefresh(!refresh)
|
||||
ToastAndroid.show('Berhasil mengeluarkan anggota', ToastAndroid.SHORT)
|
||||
} else {
|
||||
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT)
|
||||
} finally {
|
||||
setModal(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMemberAdmin() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiUpdateStatusAdminDivision({ user: hasil, id: dataMemberChoose.id, isAdmin: dataMemberChoose.isAdmin }, id)
|
||||
if (response.success) {
|
||||
setRefresh(!refresh)
|
||||
ToastAndroid.show(dataMemberChoose.isAdmin ? 'Berhasil memberhentikan admin' : 'Berhasil menjadi admin', ToastAndroid.SHORT)
|
||||
} else {
|
||||
ToastAndroid.show(response.message, ToastAndroid.SHORT)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT)
|
||||
} finally {
|
||||
setModal(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneDetail({ user: hasil, id })
|
||||
setDataDetail(response.data.division)
|
||||
setDataMember(response.data.member)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [refresh])
|
||||
|
||||
function handleChooseMember(item: PropsMember) {
|
||||
setDataMemberChoose(item)
|
||||
setModal(true)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -45,13 +123,14 @@ export default function InformationDivision() {
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mb05]}>Deskripsi Divisi</Text>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
<Text>There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable.</Text>
|
||||
<Text>{dataDetail?.desc}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefault, Styles.mv05]}>5 Anggota</Text>
|
||||
<Text style={[Styles.textDefault, Styles.mv05]}>{dataMember.length} Anggota</Text>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
<BorderBottomItem
|
||||
onPress={() => { router.push(`/division/${id}/add-member`) }}
|
||||
borderType="none"
|
||||
icon={
|
||||
<View style={[Styles.iconContent, ColorsStatus.gray]}>
|
||||
@@ -60,73 +139,29 @@ export default function InformationDivision() {
|
||||
}
|
||||
title="Tambah Anggota"
|
||||
/>
|
||||
|
||||
<BorderBottomItem
|
||||
borderType="bottom"
|
||||
onPress={() => { setModal(true) }}
|
||||
icon={
|
||||
<Image
|
||||
source={require("../../../../assets/images/user.jpeg")}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>
|
||||
}
|
||||
title="Amalia Dwi"
|
||||
rightTopInfo="Admin"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
borderType="bottom"
|
||||
onPress={() => { setModal(true) }}
|
||||
icon={
|
||||
<Image
|
||||
source={require("../../../../assets/images/user.jpeg")}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>
|
||||
}
|
||||
title="Amalia Dwi"
|
||||
rightTopInfo="Admin"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
borderType="bottom"
|
||||
onPress={() => { setModal(true) }}
|
||||
icon={
|
||||
<Image
|
||||
source={require("../../../../assets/images/user.jpeg")}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>
|
||||
}
|
||||
title="Amalia Dwi"
|
||||
rightTopInfo="Anggota"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
borderType="bottom"
|
||||
onPress={() => { setModal(true) }}
|
||||
icon={
|
||||
<Image
|
||||
source={require("../../../../assets/images/user.jpeg")}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>
|
||||
}
|
||||
title="Amalia Dwi"
|
||||
rightTopInfo="Anggota"
|
||||
/>
|
||||
<BorderBottomItem
|
||||
borderType="bottom"
|
||||
onPress={() => { setModal(true) }}
|
||||
icon={
|
||||
<Image
|
||||
source={require("../../../../assets/images/user.jpeg")}
|
||||
style={[Styles.userProfileSmall]}
|
||||
/>
|
||||
}
|
||||
title="Amalia Dwi"
|
||||
rightTopInfo="Anggota"
|
||||
/>
|
||||
{
|
||||
dataMember.map((item, index) => {
|
||||
return (
|
||||
<BorderBottomItem
|
||||
width={55}
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
onPress={() => { handleChooseMember(item) }}
|
||||
icon={
|
||||
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} size="sm" />
|
||||
}
|
||||
title={item.name}
|
||||
rightTopInfo={item.isAdmin ? "Admin" : "Anggota"}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title="Amalia">
|
||||
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title={dataMemberChoose.name}>
|
||||
<View>
|
||||
<Pressable style={[Styles.wrapItemBorderBottom]} onPress={() => { handleMemberAdmin() }}>
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
@@ -135,7 +170,7 @@ export default function InformationDivision() {
|
||||
</View>
|
||||
<View style={[Styles.rowSpaceBetween, { width: '88%' }]}>
|
||||
<View style={[Styles.ml10]}>
|
||||
<Text style={[Styles.textDefault]}>Memberhentikan sebagai admin</Text>
|
||||
<Text style={[Styles.textDefault]}>{dataMemberChoose.isAdmin ? 'Memberhentikan sebagai admin' : 'Jadikan admin'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -26,8 +26,8 @@ export default function BorderBottomItem({ title, subtitle, icon, desc, onPress,
|
||||
<Pressable style={[borderType == 'bottom' ? Styles.wrapItemBorderBottom : borderType == 'all' ? Styles.wrapItemBorderAll : Styles.wrapItemBorderNone, bgColor && bgColor == 'white' && ColorsStatus.white]} onPress={onPress}>
|
||||
<View style={[Styles.rowItemsCenter]}>
|
||||
{icon}
|
||||
<View style={[Styles.rowSpaceBetween, width ? { width: lebar } : { width: '88%' }]}>
|
||||
<View style={[Styles.ml10]}>
|
||||
<View style={[Styles.rowSpaceBetween, width ? { width: lebar } : { width: '88%' },]}>
|
||||
<View style={[Styles.ml10, width ? { width: lebar } : { width: '88%' }]}>
|
||||
<Text style={[titleWeight == 'normal' ? Styles.textDefault : Styles.textDefaultSemiBold]} numberOfLines={1} ellipsizeMode='tail'>{title}</Text>
|
||||
{
|
||||
subtitle &&
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function DiscussionItem({ title, user, date }: Props) {
|
||||
<View style={[Styles.wrapItemDiscussion]}>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mb10]}>
|
||||
<Ionicons name="chatbox-ellipses-outline" size={22} color="black" style={Styles.mr10} />
|
||||
<Text style={{ fontWeight: 'bold' }}>{title}</Text>
|
||||
<Text style={{ fontWeight: 'bold' }} numberOfLines={1} ellipsizeMode="tail">{title}</Text>
|
||||
</View>
|
||||
<View style={Styles.rowSpaceBetween}>
|
||||
<View style={Styles.rowItemsCenter}>
|
||||
|
||||
@@ -1,15 +1,49 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiGetDivisionOneFeature } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import DiscussionItem from "../discussionItem";
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
title: string
|
||||
desc: string
|
||||
user: string
|
||||
date: string
|
||||
}
|
||||
|
||||
export default function DiscussionDivisionDetail() {
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'new-discussion' })
|
||||
setData(response.data)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Diskusi</Text>
|
||||
<View style={[Styles.wrapPaper]}>
|
||||
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
|
||||
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
|
||||
<DiscussionItem title="Bagaimana cara mengatasi banjir?" user="Amalia" date="13 Februari 2025" />
|
||||
{
|
||||
data.length > 0 ?
|
||||
data.map((item, index) => (
|
||||
<DiscussionItem key={index} title={item.desc} user={item.user} date={item.date} />
|
||||
))
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada diskusi</Text>
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
||||
@@ -1,49 +1,80 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Dimensions, Text, View } from "react-native";
|
||||
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { apiGetDivisionOneFeature } from "@/lib/api";
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
name: string
|
||||
extension: string
|
||||
path: string
|
||||
share: boolean
|
||||
}
|
||||
|
||||
export default function FileDivisionDetail() {
|
||||
const data = [...new Array(6).keys()];
|
||||
const ref = React.useRef<ICarouselInstance>(null);
|
||||
const width = Dimensions.get("window").width;
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'new-file' })
|
||||
setData(response.data)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv10]}>Dokumen Terkini</Text>
|
||||
<Carousel
|
||||
ref={ref}
|
||||
width={width}
|
||||
height={115}
|
||||
data={data}
|
||||
loop={true}
|
||||
autoPlay={false}
|
||||
autoPlayReverse={false}
|
||||
pagingEnabled={true}
|
||||
snapEnabled={true}
|
||||
vertical={false}
|
||||
style={{
|
||||
width: width,
|
||||
}}
|
||||
mode="parallax"
|
||||
modeConfig={{
|
||||
parallaxScrollingScale: 1,
|
||||
parallaxScrollingOffset: 280,
|
||||
}}
|
||||
renderItem={({ index }) => (
|
||||
<View style={{ margin: 'auto', width:'28%' }}>
|
||||
<View style={{alignItems:'center'}}>
|
||||
<View style={[Styles.wrapPaper, { alignItems: 'center' }]}>
|
||||
<Feather name="file-text" size={50} color="black" style={Styles.mr05} />
|
||||
{
|
||||
data.length > 0 ?
|
||||
<Carousel
|
||||
ref={ref}
|
||||
width={width}
|
||||
height={115}
|
||||
data={data}
|
||||
loop={true}
|
||||
autoPlay={false}
|
||||
autoPlayReverse={false}
|
||||
pagingEnabled={true}
|
||||
snapEnabled={true}
|
||||
vertical={false}
|
||||
style={{
|
||||
width: width,
|
||||
}}
|
||||
mode="parallax"
|
||||
modeConfig={{
|
||||
parallaxScrollingScale: 1,
|
||||
parallaxScrollingOffset: 280,
|
||||
}}
|
||||
renderItem={({ index }) => (
|
||||
<View style={{ margin: 'auto', width: '28%' }}>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<View style={[Styles.wrapPaper, { alignItems: 'center' }]}>
|
||||
<Feather name="file-text" size={50} color="black" style={Styles.mr05} />
|
||||
</View>
|
||||
</View>
|
||||
<Text style={[Styles.textMediumNormal, { textAlign: 'center' }]} numberOfLines={1}>{data[index].name}.{data[index].extension}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text style={[Styles.textMediumNormal, { textAlign: 'center' }]} numberOfLines={1}>File_Pertama.png Amalia Dwi</Text>
|
||||
</View>
|
||||
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada file</Text>
|
||||
}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,45 @@
|
||||
import { ColorsStatus } from "@/constants/ColorsStatus"
|
||||
import Styles from "@/constants/Styles"
|
||||
import { apiGetDivisionOneFeature } from "@/lib/api"
|
||||
import { useAuthSession } from "@/providers/AuthProvider"
|
||||
import { AntDesign, MaterialIcons, SimpleLineIcons } from "@expo/vector-icons"
|
||||
import { router, useLocalSearchParams } from "expo-router"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Text, View } from "react-native"
|
||||
import BorderBottomItem from "../borderBottomItem"
|
||||
import { router, useLocalSearchParams } from "expo-router"
|
||||
|
||||
type Props = {
|
||||
tugas: number
|
||||
dokumen: number
|
||||
diskusi: number
|
||||
kalender: number
|
||||
}
|
||||
|
||||
export default function FiturDivisionDetail() {
|
||||
const { id } = useLocalSearchParams()
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props>({
|
||||
tugas: 0,
|
||||
dokumen: 0,
|
||||
diskusi: 0,
|
||||
kalender: 0,
|
||||
})
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'jumlah' })
|
||||
setData(response.data)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View style={[Styles.mb15]}>
|
||||
@@ -22,7 +55,7 @@ export default function FiturDivisionDetail() {
|
||||
</View>
|
||||
}
|
||||
title="Tugas"
|
||||
subtitle='15 Tugas'
|
||||
subtitle={`${data.tugas} Tugas`}
|
||||
width={28}
|
||||
onPress={() => { router.push(`/division/${id}/task?status=0`) }}
|
||||
/>
|
||||
@@ -36,7 +69,7 @@ export default function FiturDivisionDetail() {
|
||||
</View>
|
||||
}
|
||||
title="Dokumen"
|
||||
subtitle='20 File'
|
||||
subtitle={`${data.dokumen} File`}
|
||||
width={28}
|
||||
onPress={() => { router.push(`/division/${id}/document`) }}
|
||||
/>
|
||||
@@ -52,7 +85,7 @@ export default function FiturDivisionDetail() {
|
||||
</View>
|
||||
}
|
||||
title="Diskusi"
|
||||
subtitle='5 Diskusi'
|
||||
subtitle={`${data.diskusi} Diskusi`}
|
||||
width={28}
|
||||
onPress={() => { router.push(`/division/${id}/discussion?active=true`) }}
|
||||
/>
|
||||
@@ -66,7 +99,7 @@ export default function FiturDivisionDetail() {
|
||||
</View>
|
||||
}
|
||||
title="Kalender"
|
||||
subtitle='23 Acara'
|
||||
subtitle={`${data.kalender} Acara`}
|
||||
width={28}
|
||||
onPress={() => { router.push(`/division/${id}/calendar`) }}
|
||||
/>
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function HeaderRightDivisionDetail({ id }: Props) {
|
||||
title="Informasi Divisi"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
router.push('/division/123/info')
|
||||
router.push(`/division/${id}/info`)
|
||||
}}
|
||||
/>
|
||||
<MenuItemRow
|
||||
@@ -32,7 +32,7 @@ export default function HeaderRightDivisionDetail({ id }: Props) {
|
||||
title="Laporan Divisi"
|
||||
onPress={() => {
|
||||
setVisible(false)
|
||||
router.push('/division/123/report')
|
||||
router.push(`/division/${id}/report`)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -1,39 +1,72 @@
|
||||
import Styles from "@/constants/Styles";
|
||||
import { apiGetDivisionOneFeature } from "@/lib/api";
|
||||
import { useAuthSession } from "@/providers/AuthProvider";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import React from "react";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Dimensions, Text, View } from "react-native";
|
||||
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
|
||||
|
||||
type Props = {
|
||||
id: string
|
||||
idProject: string
|
||||
title: string
|
||||
dateStart: string
|
||||
dateEnd: string
|
||||
projectTitle: string
|
||||
}
|
||||
|
||||
export default function TaskDivisionDetail() {
|
||||
const data = [...new Array(6).keys()];
|
||||
const { token, decryptToken } = useAuthSession()
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
const [data, setData] = useState<Props[]>([])
|
||||
const ref = React.useRef<ICarouselInstance>(null);
|
||||
const width = Dimensions.get("window").width;
|
||||
|
||||
async function handleLoad() {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetDivisionOneFeature({ user: hasil, id, cat: 'today-task' })
|
||||
setData(response.data)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLoad()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mb05]}>Tugas Hari Ini</Text>
|
||||
<Carousel
|
||||
ref={ref}
|
||||
style={{ width: "100%" }}
|
||||
width={width * 0.8}
|
||||
height={100}
|
||||
data={data}
|
||||
loop={true}
|
||||
autoPlay={false}
|
||||
autoPlayReverse={false}
|
||||
pagingEnabled={true}
|
||||
snapEnabled={true}
|
||||
vertical={false}
|
||||
renderItem={({ index }) => (
|
||||
<View style={[Styles.wrapPaper, { width: '95%'}]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]}>Rancangan Laporan - Laporan 1</Text>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
|
||||
<Feather name="clock" size={18} color="grey" style={Styles.mr05} />
|
||||
<Text style={[Styles.textInformation]}>5 Mar 2025 - 12 Mar 2025</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
{
|
||||
data.length > 0 ?
|
||||
<Carousel
|
||||
ref={ref}
|
||||
style={{ width: "100%" }}
|
||||
width={width * 0.8}
|
||||
height={100}
|
||||
data={data}
|
||||
loop={true}
|
||||
autoPlay={false}
|
||||
autoPlayReverse={false}
|
||||
pagingEnabled={true}
|
||||
snapEnabled={true}
|
||||
vertical={false}
|
||||
renderItem={({ index }) => (
|
||||
<View style={[Styles.wrapPaper, { width: '95%' }]}>
|
||||
<Text style={[Styles.textDefaultSemiBold]} numberOfLines={1} ellipsizeMode="tail">{data[index].title} - {data[index].projectTitle}</Text>
|
||||
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
|
||||
<Feather name="clock" size={18} color="grey" style={Styles.mr05} />
|
||||
<Text style={[Styles.textInformation]} numberOfLines={1} ellipsizeMode="tail">{data[index].dateStart} - {data[index].dateEnd}</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
:
|
||||
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada tugas</Text>
|
||||
}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ export default function ImageWithLabel({ src, label, onClick }: Props) {
|
||||
return (
|
||||
<TouchableOpacity style={[Styles.contentItemCenter, Styles.mh05]} onPress={onClick}>
|
||||
<ImageUser src={src} border />
|
||||
<Text>{label}</Text>
|
||||
<Text numberOfLines={1} ellipsizeMode="tail">{label}</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
27
lib/api.ts
27
lib/api.ts
@@ -357,4 +357,29 @@ export const apiGetDivision = async ({ user, search, group, kategori, active }:
|
||||
export const apiGetDivisionReport = async ({ user, cat, date, dateEnd, division, group }: { user: string, cat: string, date: string, dateEnd: string, division: string, group?: string }) => {
|
||||
const response = await api.get(`mobile/division/report?user=${user}&cat=${cat}&date=${date}&date-end=${dateEnd}&division=${division}&group=${group}`);
|
||||
return response.data;
|
||||
};
|
||||
};
|
||||
|
||||
export const apiGetDivisionOneFeature = async ({ user, cat, id }: { user: string, cat: 'jumlah' | 'today-task' | 'new-file' | 'new-discussion', id: string }) => {
|
||||
const response = await api.get(`mobile/division/${id}/detail?user=${user}&cat=${cat}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiGetDivisionOneDetail = async ({ user, id }: { user: string, id: string }) => {
|
||||
const response = await api.get(`mobile/division/${id}?user=${user}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiUpdateStatusAdminDivision = async (data: { user: string, id: string, isAdmin: boolean }, id: string) => {
|
||||
const response = await api.put(`mobile/division/${id}/detail`, data)
|
||||
return response.data
|
||||
};
|
||||
|
||||
export const apiDeleteMemberDivision = async (data: { user: string, id: string }, id: string) => {
|
||||
const response = await api.delete(`/mobile/division/${id}/detail`, { data })
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const apiAddMemberDivision = async ({ data, id }: { data: { user: string, member: any[] }, id: string }) => {
|
||||
const response = await api.post(`/mobile/division/${id}/detail`, data)
|
||||
return response.data;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user