Compare commits

...

7 Commits

Author SHA1 Message Date
abeb26e565 Merge pull request 'fix : tampilan' (#29) from amalia/26-agustus-25 into join
Reviewed-on: bip/mobile-darmasaba#29
2025-08-26 17:23:42 +08:00
191699af04 fix : tampilan
Deskripsi:
- text panjang pada pengumuman
- text panjang pada list banner
- text align pada detail member
- text panjang pada section item tanggal tugas
- text panjang pada select form
- text panjang pada detail event calendar divisi
- keyboard avoiding pada edit event calendar divisi

No Issues
2025-08-26 16:35:25 +08:00
5cb81856de Merge pull request 'amalia/22-agustus-25' (#28) from amalia/22-agustus-25 into join
Reviewed-on: bip/mobile-darmasaba#28
2025-08-22 17:42:40 +08:00
37fda41dc1 upd: tampilan
Deskripsi:
- jarak setelah input text pencarian

No Issues
2025-08-22 16:40:31 +08:00
298113488c upd: task divisi
Deskripsi:
- update role akses task divisi

No Issues'
2025-08-22 16:29:52 +08:00
d88c332b03 upd: tampilan
Deskripsi:
- vertical center icon list dan grid pada list project dan divisi
- mb list lembaga desa dan search page

No Issues
2025-08-22 12:15:45 +08:00
f5c29e86fa upd : banner
Deskripsi:
- home > ketika tidak ada data banner
- banner list > ketika tidak ada data banner

No Issues
2025-08-22 12:00:23 +08:00
29 changed files with 354 additions and 280 deletions

View File

@@ -84,9 +84,9 @@ export default function DetailAnnouncement() {
</View>
:
<>
<View style={Styles.rowItemsCenter}>
<View style={[Styles.rowItemsCenter, { alignItems: 'flex-start' }]}>
<MaterialIcons name="campaign" size={30} color="black" style={Styles.mr05} />
<Text style={[Styles.textDefaultSemiBold]}>{data?.title}</Text>
<Text style={[Styles.textDefaultSemiBold, Styles.w90]}>{data?.title}</Text>
</View>
<View style={[Styles.mt10]}>
{

View File

@@ -87,7 +87,7 @@ export default function Announcement() {
<View>
<InputSearch onChange={setSearch} />
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item, index) => {

View File

@@ -5,6 +5,7 @@ import ButtonBackHeader from "@/components/buttonBackHeader"
import DrawerBottom from "@/components/drawerBottom"
import MenuItemRow from "@/components/menuItemRow"
import ModalLoading from "@/components/modalLoading"
import Text from "@/components/Text"
import { ConstEnv } from "@/constants/ConstEnv"
import Styles from "@/constants/Styles"
import { apiDeleteBanner, apiGetBanner } from "@/lib/api"
@@ -121,26 +122,37 @@ export default function BannerList() {
}
style={[Styles.h100]}
>
<View style={[Styles.p15, Styles.mb100]}>
{entities.map((index: any, key: number) => (
<BorderBottomItem
key={key}
onPress={() => {
setDataId(index.id)
setSelectFile(index)
setModal(true)
}}
borderType="all"
icon={
<Image
source={{ uri: `${ConstEnv.url_storage}/files/${index.image}` }}
style={[Styles.imgListBanner]}
{
entities.length > 0
?
<View style={[Styles.p15, Styles.mb100]}>
{entities.map((index: any, key: number) => (
<BorderBottomItem
key={key}
onPress={() => {
setDataId(index.id)
setSelectFile(index)
setModal(true)
}}
borderType="all"
icon={
<Image
source={{ uri: `${ConstEnv.url_storage}/files/${index.image}` }}
style={[Styles.imgListBanner]}
/>
}
title={index.title}
width={65}
/>
}
title={index.title}
/>
))}
</View>
))}
</View>
:
<View style={[Styles.p15, Styles.mb100]}>
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
</View>
}
</ScrollView>
<DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title="Menu">

View File

@@ -122,7 +122,7 @@ export default function Discussion() {
</View>
}
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item: any, i: number) => {

View File

@@ -9,10 +9,11 @@ import { valueTypeEventRepeat } from "@/constants/TypeEventRepeat"
import { apiGetCalendarOne, apiUpdateCalendar } from "@/lib/api"
import { stringToDateTime } from "@/lib/fun_stringToDate"
import { useAuthSession } from "@/providers/AuthProvider"
import { useHeaderHeight } from "@react-navigation/elements"
import { Stack, router, useLocalSearchParams } from "expo-router"
import moment from "moment"
import { useEffect, useState } from "react"
import { SafeAreaView, ScrollView, View } from "react-native"
import { KeyboardAvoidingView, Platform, SafeAreaView, ScrollView, View } from "react-native"
import Toast from "react-native-toast-message"
export default function EditEventCalendar() {
@@ -22,6 +23,7 @@ export default function EditEventCalendar() {
const { id, detail } = useLocalSearchParams<{ id: string, detail: string }>()
const [idCalendar, setIdCalendar] = useState('')
const [loading, setLoading] = useState(false)
const headerHeight = useHeaderHeight()
const [error, setError] = useState({
title: false,
@@ -176,94 +178,100 @@ export default function EditEventCalendar() {
/>
}}
/>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
<InputForm
label="Nama Acara"
type="default"
placeholder="Nama Acara"
required
bg="white"
value={data.title}
onChange={(val) => validationForm("title", val)}
error={error.title}
errorText="Nama acara tidak boleh kosong"
/>
<InputDate
onChange={(val) => validationForm("dateStart", val)}
mode="date"
value={data.dateStart}
label="Tanggal Acara"
required
error={error.dateStart}
errorText="Tanggal acara tidak boleh kosong"
placeholder="Pilih Tanggal Acara"
/>
<View style={[Styles.rowSpaceBetween, Styles.mv10]}>
<View style={[{ width: "48%" }]}>
<InputDate
onChange={(val) => validationForm("timeStart", val)}
mode="time"
value={data.timeStart}
label="Waktu Awal"
required
error={error.timeStart}
errorText="Waktu awal tidak valid"
placeholder="--:--"
/>
</View>
<View style={[{ width: "48%" }]}>
<InputDate
onChange={(val) => validationForm("timeEnd", val)}
mode="time"
value={data.timeEnd}
label="Waktu Akhir"
required
error={error.timeEnd}
errorText="Waktu akhir tidak valid"
placeholder="--:--"
/>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerHeight}
>
<ScrollView>
<View style={[Styles.p15]}>
<InputForm
label="Nama Acara"
type="default"
placeholder="Nama Acara"
required
bg="white"
value={data.title}
onChange={(val) => validationForm("title", val)}
error={error.title}
errorText="Nama acara tidak boleh kosong"
/>
<InputDate
onChange={(val) => validationForm("dateStart", val)}
mode="date"
value={data.dateStart}
label="Tanggal Acara"
required
error={error.dateStart}
errorText="Tanggal acara tidak boleh kosong"
placeholder="Pilih Tanggal Acara"
/>
<View style={[Styles.rowSpaceBetween, Styles.mv10]}>
<View style={[{ width: "48%" }]}>
<InputDate
onChange={(val) => validationForm("timeStart", val)}
mode="time"
value={data.timeStart}
label="Waktu Awal"
required
error={error.timeStart}
errorText="Waktu awal tidak valid"
placeholder="--:--"
/>
</View>
<View style={[{ width: "48%" }]}>
<InputDate
onChange={(val) => validationForm("timeEnd", val)}
mode="time"
value={data.timeEnd}
label="Waktu Akhir"
required
error={error.timeEnd}
errorText="Waktu akhir tidak valid"
placeholder="--:--"
/>
</View>
</View>
<InputForm
label="Link Meet"
type="default"
placeholder="Link Meet"
bg="white"
value={data.linkMeet}
onChange={(val) => validationForm("linkMeet", val)}
/>
<SelectForm
bg="white"
label="Ulangi Acara"
placeholder="Ulangi Acara"
value={choose.label}
required
onPress={() => { setSelect(true) }}
/>
<InputForm
label="Jumlah Pengulangan"
type="numeric"
placeholder="Jumlah Pengulangan"
required
bg="white"
value={String(data.repeatValue)}
onChange={(val) => validationForm("repeatValue", val)}
error={error.repeatValue}
errorText="Jumlah pengulangan tidak valid"
disable={choose.val == "once"}
/>
<InputForm
label="Deskripsi"
type="default"
placeholder="Deskripsi"
bg="white"
value={data.desc}
onChange={(val) => validationForm("desc", val)}
multiline
/>
</View>
<InputForm
label="Link Meet"
type="default"
placeholder="Link Meet"
bg="white"
value={data.linkMeet}
onChange={(val) => validationForm("linkMeet", val)}
/>
<SelectForm
bg="white"
label="Ulangi Acara"
placeholder="Ulangi Acara"
value={choose.label}
required
onPress={() => { setSelect(true) }}
/>
<InputForm
label="Jumlah Pengulangan"
type="numeric"
placeholder="Jumlah Pengulangan"
required
bg="white"
value={String(data.repeatValue)}
onChange={(val) => validationForm("repeatValue", val)}
error={error.repeatValue}
errorText="Jumlah pengulangan tidak valid"
disable={choose.val == "once"}
/>
<InputForm
label="Deskripsi"
type="default"
placeholder="Deskripsi"
bg="white"
value={data.desc}
onChange={(val) => validationForm("desc", val)}
multiline
/>
</View>
</ScrollView>
</ScrollView>
</KeyboardAvoidingView>
<ModalSelect
category={"type-event-repeat"}

View File

@@ -165,12 +165,12 @@ export default function DetailEventCalendar() {
>
<View style={[Styles.p15]}>
<View style={[Styles.wrapPaper, Styles.mb15]}>
<View style={Styles.rowItemsCenter}>
<View style={[Styles.rowItemsCenter, { alignItems: 'flex-start' }]}>
<MaterialCommunityIcons name="calendar-text" size={30} color="black" style={Styles.mr10} />
{
loading ?
<Skeleton width={80} height={10} borderRadius={10} widthType="percent" />
: <Text style={[Styles.textDefault]}>{data?.title}</Text>
: <Text style={[Styles.textDefault, Styles.w90]}>{data?.title}</Text>
}
</View>
@@ -219,13 +219,13 @@ export default function DetailEventCalendar() {
<Text style={[Styles.textDefault]}>{data?.linkMeet ? data.linkMeet : '-'}</Text>
}
</View>
<View style={[Styles.rowItemsCenter, Styles.mt10]}>
<View style={[Styles.rowItemsCenter, Styles.mt10, {alignItems:'flex-start'}]}>
<MaterialCommunityIcons name="card-text-outline" size={30} color="black" style={Styles.mr10} />
{
loading ?
<Skeleton width={80} height={10} borderRadius={10} widthType="percent" />
:
<Text style={[Styles.textDefault]}>{data?.desc}</Text>
<Text style={[Styles.textDefault, Styles.w90]}>{data?.desc}</Text>
}
</View>
</View>

View File

@@ -121,7 +121,7 @@ export default function DiscussionDivision() {
<InputSearch onChange={setSearch} />
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item: any, i: number) => {

View File

@@ -8,7 +8,7 @@ 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";
import { apiGetDivisionOneFeature, apiGetTaskOne } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
@@ -32,6 +32,35 @@ export default function DetailTaskDivision() {
const [progress, setProgress] = useState(0)
const update = useSelector((state: any) => state.taskUpdate)
const [refreshing, setRefreshing] = useState(false)
const [isMemberDivision, setIsMemberDivision] = useState(false);
const [isAdminDivision, setIsAdminDivision] = useState(false);
const entityUser = useSelector((state: any) => state.user);
async function handleCheckMember() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetDivisionOneFeature({
id,
user: hasil,
cat: "check-member",
});
setIsMemberDivision(response.data);
const response2 = await apiGetDivisionOneFeature({
id,
user: hasil,
cat: "check-admin",
});
setIsAdminDivision(response2.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleCheckMember()
}, [])
async function handleLoad(cat: 'data' | 'progress') {
@@ -74,7 +103,9 @@ export default function DetailTaskDivision() {
headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
headerTitle: loading ? 'Loading... ' : data?.title,
headerTitleAlign: 'center',
headerRight: () => <HeaderRightTaskDetail id={detail} division={id} status={data?.status} />,
headerRight: () => (entityUser.role == "user" || entityUser.role == "coadmin") && !isMemberDivision
? <></>
: <HeaderRightTaskDetail id={detail} division={id} status={data?.status} isAdminDivision={isAdminDivision} />,
}}
/>
<ScrollView
@@ -91,10 +122,10 @@ export default function DetailTaskDivision() {
}
<SectionProgress text={`Kemajuan Kegiatan ${progress}%`} progress={progress} />
<SectionReportTask refreshing={refreshing} />
<SectionTanggalTugasTask refreshing={refreshing} />
<SectionFileTask refreshing={refreshing} />
<SectionLinkTask refreshing={refreshing} />
<SectionMemberTask refreshing={refreshing} />
<SectionTanggalTugasTask refreshing={refreshing} isMemberDivision={isMemberDivision} />
<SectionFileTask refreshing={refreshing} isMemberDivision={isMemberDivision} />
<SectionLinkTask refreshing={refreshing} isMemberDivision={isMemberDivision} />
<SectionMemberTask refreshing={refreshing} isMemberDivision={isMemberDivision} />
</View>
</ScrollView>
</SafeAreaView>

View File

@@ -179,7 +179,7 @@ export default function ListTask() {
</Pressable>
</View>
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
isList ?

View File

@@ -180,7 +180,7 @@ export default function ListDivision() {
</View>
}
<View style={[Styles.rowSpaceBetween]}>
<View style={[Styles.rowSpaceBetween, { alignItems: 'center' }]}>
<InputSearch width={68} onChange={setSearch} />
<Pressable
onPress={() => {
@@ -200,7 +200,7 @@ export default function ListDivision() {
</View>
)}
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
isList ?

View File

@@ -126,7 +126,7 @@ export default function Index() {
return (
<View style={[Styles.p15, { flex: 1 }]}>
<View>
<View style={[Styles.mb10]}>
<View style={[Styles.wrapBtnTab]}>
<ButtonTab
active={status == "false" ? "false" : "true"}
@@ -145,7 +145,7 @@ export default function Index() {
</View>
<InputSearch onChange={setSearch} />
</View>
<View style={{ flex: 2 }}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item, index) => {

View File

@@ -95,7 +95,7 @@ export default function MemberDetail() {
:
<>
<ImageUser src={`${ConstEnv.url_storage}/files/${data?.img}`} size="lg" />
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>{data?.name}</Text>
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10, { textAlign: 'center' }]}>{data?.name}</Text>
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{data?.role}</Text>
</>

View File

@@ -129,7 +129,7 @@ export default function Index() {
</View>
}
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item, index) => {

View File

@@ -165,7 +165,7 @@ export default function Index() {
</View>
}
</View>
<View style={[{ flex: 2 }]}>
<View style={[{ flex: 2 }, Styles.mt05]}>
{
loading ?
arrSkeleton.map((item, index) => {

View File

@@ -178,7 +178,7 @@ export default function ListProject() {
n={4}
/>
</ScrollView>
<View style={[Styles.rowSpaceBetween]}>
<View style={[Styles.rowSpaceBetween, { alignItems: 'center' }]}>
<InputSearch width={68} onChange={setSearch} />
<Pressable
onPress={() => {

View File

@@ -75,7 +75,6 @@ export default function Search() {
headerTitleAlign: 'center'
}}
/>
{/* <ScrollView> */}
<View style={[Styles.p15]}>
<InputSearch onChange={handleSearch} />
{
@@ -163,13 +162,12 @@ export default function Search() {
</View>
:
<View style={Styles.contentItemCenter}>
<View style={[Styles.contentItemCenter, Styles.mt10]}>
<Text style={[Styles.textInformation, Styles.cGray]}>Tidak ada data</Text>
</View>
}
</View>
{/* </ScrollView> */}
</SafeAreaView>
</>
)

View File

@@ -44,7 +44,7 @@ export default function DrawerBottom({ isVisible, setVisible, title, children, a
>
<View style={[Styles.modalContentNew, { height: tinggiFix }]}>
<View style={[Styles.titleContainerNew]}>
<Text style={Styles.textDefault}>{title}</Text>
<Text numberOfLines={1} ellipsizeMode='tail' style={[Styles.textDefault, Styles.w90]}>{title}</Text>
<Pressable onPress={() => setVisible(false)}>
<MaterialIcons name="close" color="black" size={22} />
</Pressable>
@@ -57,7 +57,7 @@ export default function DrawerBottom({ isVisible, setVisible, title, children, a
:
<View style={[Styles.modalContentNew, { height: tinggiFix }]}>
<View style={[Styles.titleContainerNew]}>
<Text style={Styles.textDefault}>{title}</Text>
<Text numberOfLines={1} ellipsizeMode='tail' style={[Styles.textDefault, Styles.w90]}>{title}</Text>
<Pressable onPress={() => setVisible(false)}>
<MaterialIcons name="close" color="black" size={22} />
</Pressable>

View File

@@ -1,5 +1,5 @@
import Styles from "@/constants/Styles"
import { Pressable, View } from "react-native"
import Styles from "@/constants/Styles";
import { Pressable, View } from "react-native";
import Text from "./Text";
type Props = {
@@ -17,8 +17,8 @@ export default function EventItem({ category, title, user, jamAwal, jamAkhir, on
<View style={[Styles.dividerEvent, { backgroundColor: category == 'orange' ? '#FB804C' : '#535FCA' }]} />
<View>
<Text>{jamAwal} - {jamAkhir}</Text>
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>{title}</Text>
<Text>Dibuat oleh : {user}</Text>
<Text numberOfLines={1} ellipsizeMode="tail" style={[Styles.textDefaultSemiBold, Styles.mv05]}>{title}</Text>
<Text numberOfLines={1} ellipsizeMode="tail">Dibuat oleh : {user}</Text>
</View>
</Pressable>
)

View File

@@ -9,6 +9,7 @@ import { Dimensions, Image, View } from "react-native";
import { useSharedValue } from "react-native-reanimated";
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
import { useDispatch, useSelector } from "react-redux";
import Text from "../Text";
export default function CaraouselHome() {
const { decryptToken, token } = useAuthSession()
@@ -21,7 +22,13 @@ export default function CaraouselHome() {
async function handleBannerView() {
const hasil = await decryptToken(String(token?.current))
apiGetBanner({ user: hasil }).then((data) => dispatch(setEntities(data.data)))
apiGetBanner({ user: hasil }).then((data) => {
if (data.data.length > 0) {
dispatch(setEntities(data.data))
} else {
dispatch(setEntities([]))
}
})
}
async function handleUser() {
@@ -40,22 +47,30 @@ export default function CaraouselHome() {
return (
<View style={[Styles.mv15]}>
<Carousel
ref={ref}
width={width}
height={width / 2.5}
data={entities}
loop={true}
autoPlay={true}
autoPlayInterval={5000}
onProgressChange={progress}
renderItem={({ index }) => (
<Image
source={{ uri: `${ConstEnv.url_storage}/files/${entities[index].image}` }}
style={[Styles.caraoselContent]}
{
entities.length > 0 ?
<Carousel
ref={ref}
width={width}
height={width / 2.5}
data={entities}
loop={true}
autoPlay={true}
autoPlayInterval={5000}
onProgressChange={progress}
renderItem={({ index }) => (
<Image
source={{ uri: `${ConstEnv.url_storage}/files/${entities[index].image}` }}
style={[Styles.caraoselContent]}
/>
)}
/>
)}
/>
:
<View style={[Styles.caraoselContent, { height: width / 2.5 }]}>
<Text style={[Styles.textDefault, Styles.cWhite, { textAlign: 'center' }]}>BANNER</Text>
</View>
}
</View>
)
}

View File

@@ -19,15 +19,16 @@ type Props = {
value?: string
disable?: boolean
multiline?: boolean
mb?: boolean
};
export function InputForm({ label, value, placeholder, onChange, info, disable, error, errorText, required, itemLeft, itemRight, type, round, width, bg, multiline }: Props) {
export function InputForm({ label, value, placeholder, onChange, info, disable, error, errorText, required, itemLeft, itemRight, type, round, width, bg, multiline, mb = true }: Props) {
const lebar = Dimensions.get("window").width;
if (itemLeft != undefined || itemRight != undefined) {
return (
<View style={{ marginBottom: 10 }}>
<View style={[mb && Styles.mb10]}>
{
label != undefined && (
<Text style={[{ marginBottom: 5, textTransform: "capitalize" }, error && Styles.cError]}>

View File

@@ -12,6 +12,7 @@ export default function InputSearch({ onChange, width, value }: { onChange?: (va
width={width}
bg="white"
value={value}
mb={false}
/>
)
}

View File

@@ -33,7 +33,7 @@ export default function ItemSectionTanggalTugas({ done, title, dateStart, dateEn
</View>
<View style={[Styles.wrapPaper, Styles.mv10, Styles.p10]}>
<View style={[Styles.rowItemsCenter]}>
<View style={[Styles.rowItemsCenter, {alignItems:'flex-start'}]}>
<MaterialCommunityIcons name="file-table-outline" size={25} color="black" style={[Styles.mr10]} />
<View style={[Styles.w90]}>
<Text style={[Styles.textDefault]}>{title}</Text>

View File

@@ -34,9 +34,9 @@ export default function SelectForm({ label, value, placeholder, onPress, info, e
<Feather name="chevron-right" size={20} color="grey" />
{
value ? (
<Text style={[Styles.cBlack]}>{value}</Text>
<Text numberOfLines={1} ellipsizeMode='tail' style={[Styles.cBlack, Styles.w90]}>{value}</Text>
) : (
<Text style={[Styles.cGray]}>{placeholder}</Text>
<Text numberOfLines={1} ellipsizeMode='tail' style={[Styles.cGray, Styles.w90]}>{placeholder}</Text>
)
}
</View>

View File

@@ -1,10 +1,10 @@
import Styles from "@/constants/Styles"
import { apiAddLinkTask, apiDeleteTask, apiGetDivisionOneFeature } from "@/lib/api"
import { apiAddLinkTask, apiDeleteTask } from "@/lib/api"
import { setUpdateTask } from "@/lib/taskUpdate"
import { useAuthSession } from "@/providers/AuthProvider"
import { AntDesign, Feather, Ionicons, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons"
import { router } from "expo-router"
import { useEffect, useState } from "react"
import { useState } from "react"
import { View } from "react-native"
import Toast from "react-native-toast-message"
import { useDispatch, useSelector } from "react-redux"
@@ -18,46 +18,19 @@ import ModalFloat from "../modalFloat"
type Props = {
id: string | string[]
division: string
status: number | undefined
status: number | undefined,
isAdminDivision: boolean
}
export default function HeaderRightTaskDetail({ id, division, status }: Props) {
export default function HeaderRightTaskDetail({ id, division, status, isAdminDivision }: Props) {
const { token, decryptToken } = useAuthSession()
const [isVisible, setVisible] = useState(false)
const entityUser = useSelector((state: any) => state.user);
const [isMemberDivision, setIsMemberDivision] = useState(false);
const [isAdminDivision, setIsAdminDivision] = useState(false);
const dispatch = useDispatch()
const update = useSelector((state: any) => state.taskUpdate)
const [isAddLink, setAddLink] = useState(false)
const [link, setLink] = useState("")
async function handleCheckMember() {
try {
const hasil = await decryptToken(String(token?.current));
const response = await apiGetDivisionOneFeature({
id: division,
user: hasil,
cat: "check-member",
});
setIsMemberDivision(response.data);
const response2 = await apiGetDivisionOneFeature({
id: division,
user: hasil,
cat: "check-admin",
});
setIsAdminDivision(response2.data);
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleCheckMember()
}, [])
async function handleDelete() {
try {
const hasil = await decryptToken(String(token?.current))
@@ -95,12 +68,7 @@ export default function HeaderRightTaskDetail({ id, division, status }: Props) {
return (
<>
{
(entityUser.role == "user" || entityUser.role == "coadmin") && !isMemberDivision
? <></>
:
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
}
<ButtonMenuHeader onPress={() => { setVisible(true) }} />
<DrawerBottom animation="slide" isVisible={isVisible} setVisible={setVisible} title="Menu" height={30}>
<View style={Styles.rowItemsCenter}>
<MenuItemRow

View File

@@ -28,7 +28,7 @@ type Props = {
idStorage: string
}
export default function SectionFileTask({ refreshing }: { refreshing: boolean }) {
export default function SectionFileTask({ refreshing, isMemberDivision }: { refreshing: boolean, isMemberDivision: boolean }) {
const [isModal, setModal] = useState(false)
const { token, decryptToken } = useAuthSession()
const { detail } = useLocalSearchParams<{ detail: string }>()
@@ -39,6 +39,7 @@ export default function SectionFileTask({ refreshing }: { refreshing: boolean })
const arrSkeleton = Array.from({ length: 5 })
const [selectFile, setSelectFile] = useState<Props | null>(null)
const [loadingOpen, setLoadingOpen] = useState(false)
const entityUser = useSelector((state: any) => state.user);
async function handleLoad(loading: boolean) {
try {
@@ -163,21 +164,28 @@ export default function SectionFileTask({ refreshing }: { refreshing: boolean })
openFile()
}}
/>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
onPress: () => {
handleDelete()
}
})
{
(entityUser.role != "user" && entityUser.role != "coadmin") || isMemberDivision
?
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan',
onPress: () => {
handleDelete()
}
})
}}
/>
:
<></>
}
}}
/>
</View>
</DrawerBottom>
</>

View File

@@ -20,7 +20,7 @@ type Props = {
link: string
}
export default function SectionLinkTask({ refreshing }: { refreshing: boolean }) {
export default function SectionLinkTask({ refreshing, isMemberDivision }: { refreshing: boolean, isMemberDivision: boolean }) {
const [isModal, setModal] = useState(false)
const { token, decryptToken } = useAuthSession()
const { detail } = useLocalSearchParams<{ detail: string }>()
@@ -28,6 +28,7 @@ export default function SectionLinkTask({ refreshing }: { refreshing: boolean })
const update = useSelector((state: any) => state.taskUpdate)
const dispatch = useDispatch()
const [selectLink, setSelectLink] = useState<Props | null>(null)
const entityUser = useSelector((state: any) => state.user);
async function handleLoad() {
try {
@@ -101,18 +102,25 @@ export default function SectionLinkTask({ refreshing }: { refreshing: boolean })
Linking.openURL(urlCompleted(String(selectLink?.link)))
}}
/>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan',
onPress: () => { handleDelete() }
})
}}
/>
{
(entityUser.role != "user" && entityUser.role != "coadmin") || isMemberDivision
?
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah Anda yakin ingin menghapus link ini? Link yang dihapus tidak dapat dikembalikan',
onPress: () => { handleDelete() }
})
}}
/>
:
<></>
}
</View>
</DrawerBottom>
</>

View File

@@ -26,8 +26,9 @@ type Props = {
position: string;
};
export default function SectionMemberTask({ refreshing }: { refreshing: boolean }) {
export default function SectionMemberTask({ refreshing, isMemberDivision }: { refreshing: boolean, isMemberDivision: boolean }) {
const [isModal, setModal] = useState(false);
const entityUser = useSelector((state: any) => state.user);
const { token, decryptToken } = useAuthSession();
const { id, detail } = useLocalSearchParams<{ id: string; detail: string }>();
const [data, setData] = useState<Props[]>([]);
@@ -165,24 +166,31 @@ export default function SectionMemberTask({ refreshing }: { refreshing: boolean
}}
/>
<MenuItemRow
icon={
<MaterialCommunityIcons
name="account-remove"
color="black"
size={25}
{
(entityUser.role != "user" && entityUser.role != "coadmin") || isMemberDivision
?
<MenuItemRow
icon={
<MaterialCommunityIcons
name="account-remove"
color="black"
size={25}
/>
}
title="Keluarkan"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: "Konfirmasi",
desc: "Apakah Anda yakin ingin mengeluarkan anggota?",
onPress: () => { handleDeleteMember() },
});
}}
/>
}
title="Keluarkan"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: "Konfirmasi",
desc: "Apakah Anda yakin ingin mengeluarkan anggota?",
onPress: () => { handleDeleteMember() },
});
}}
/>
:
<></>
}
</View>
</DrawerBottom>
</>

View File

@@ -26,8 +26,9 @@ type Props = {
dateEnd: string;
}
export default function SectionTanggalTugasTask({ refreshing }: { refreshing: boolean }) {
export default function SectionTanggalTugasTask({ refreshing, isMemberDivision }: { refreshing: boolean, isMemberDivision: boolean }) {
const dispatch = useDispatch()
const entityUser = useSelector((state: any) => state.user);
const update = useSelector((state: any) => state.taskUpdate)
const [isModal, setModal] = useState(false)
const [isSelect, setSelect] = useState(false)
@@ -155,24 +156,6 @@ export default function SectionTanggalTugasTask({ refreshing }: { refreshing: bo
<DrawerBottom animation="slide" isVisible={isModal} setVisible={setModal} title="Menu">
<View style={Styles.rowItemsCenter}>
<MenuItemRow
icon={<MaterialCommunityIcons name="list-status" color="black" size={25} />}
title="Update Status"
onPress={() => {
setModal(false)
setTimeout(() => {
setSelect(true)
}, 600);
}}
/>
<MenuItemRow
icon={<MaterialCommunityIcons name="pencil-outline" color="black" size={25} />}
title="Edit Tugas"
onPress={() => {
setModal(false)
router.push(`./update/${tugas.id}`)
}}
/>
<MenuItemRow
icon={
<MaterialCommunityIcons
@@ -189,24 +172,57 @@ export default function SectionTanggalTugasTask({ refreshing }: { refreshing: bo
}, 600)
}}
/>
</View>
<View style={[Styles.rowItemsCenter, Styles.mt15]}>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus Tugas"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin menghapus data ini?',
onPress: () => {
handleDelete()
}
})
{
(entityUser.role != "user" && entityUser.role != "coadmin") || isMemberDivision
?
<>
<MenuItemRow
icon={<MaterialCommunityIcons name="list-status" color="black" size={25} />}
title="Update Status"
onPress={() => {
setModal(false)
setTimeout(() => {
setSelect(true)
}, 600);
}}
/>
<MenuItemRow
icon={<MaterialCommunityIcons name="pencil-outline" color="black" size={25} />}
title="Edit Tugas"
onPress={() => {
setModal(false)
router.push(`./update/${tugas.id}`)
}}
/>
</>
:
<></>
}
}}
/>
</View>
{
(entityUser.role != "user" && entityUser.role != "coadmin") || isMemberDivision
?
<View style={[Styles.rowItemsCenter, Styles.mt15]}>
<MenuItemRow
icon={<Ionicons name="trash" color="black" size={25} />}
title="Hapus Tugas"
onPress={() => {
setModal(false)
AlertKonfirmasi({
title: 'Konfirmasi',
desc: 'Apakah anda yakin ingin menghapus data ini?',
onPress: () => {
handleDelete()
}
})
}}
/>
</View>
:
<></>
}
</DrawerBottom>
<ModalSelect

View File

@@ -515,7 +515,7 @@ const Styles = StyleSheet.create({
wrapBtnTab: {
justifyContent: 'space-between',
flexDirection: 'row',
marginBottom: 15,
marginBottom: 10,
borderRadius: 20,
padding: 5,
backgroundColor: 'white',