upd: skeleton

Deskripsi:
- diskusi umum
- detail diskusi umum
- list pengumuman
- detail pengumuman
- list kegiatan
- detail kegiatan

No Issues
This commit is contained in:
amel
2025-06-03 17:43:45 +08:00
parent 36294ec4eb
commit 1e6a6d08ae
20 changed files with 541 additions and 293 deletions

View File

@@ -4,6 +4,8 @@ import HeaderRightDiscussionGeneralDetail from "@/components/discussion_general/
import ImageUser from "@/components/imageNew";
import { InputForm } from "@/components/inputForm";
import LabelStatus from "@/components/labelStatus";
import Skeleton from "@/components/skeleton";
import SkeletonContent from "@/components/skeletonContent";
import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { apiGetDiscussionGeneralOne, apiSendDiscussionGeneralCommentar } from "@/lib/api";
@@ -41,12 +43,22 @@ export default function DetailDiscussionGeneral() {
const [memberDiscussion, setMemberDiscussion] = useState(false)
const [komentar, setKomentar] = useState('')
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
const [loading, setLoading] = useState(true)
const [loadingKomentar, setLoadingKomentar] = useState(true)
const arrSkeleton = Array.from({ length: 3 }, (_, index) => index)
async function handleLoad(cat: 'detail' | 'komentar' | 'cek-anggota') {
async function handleLoad(cat: 'detail' | 'komentar' | 'cek-anggota', loading: boolean) {
try {
if (cat == "detail") {
setLoading(loading)
} else if (cat == "komentar") {
setLoadingKomentar(loading)
}
const hasil = await decryptToken(String(token?.current))
const response = await apiGetDiscussionGeneralOne({ id: id, user: hasil, cat })
if (cat == 'detail') {
setData(response.data)
} else if (cat == 'komentar') {
@@ -54,17 +66,27 @@ export default function DetailDiscussionGeneral() {
} else if (cat == 'cek-anggota') {
setMemberDiscussion(response.data)
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
setLoadingKomentar(false)
}
}
useEffect(() => {
handleLoad('detail')
handleLoad('komentar')
handleLoad('cek-anggota')
handleLoad('detail', false)
handleLoad('komentar', false)
handleLoad('cek-anggota', false)
}, [update]);
useEffect(() => {
handleLoad('detail', true)
handleLoad('komentar', true)
handleLoad('cek-anggota', true)
}, []);
async function handleKomentar() {
try {
if (komentar != '') {
@@ -72,7 +94,7 @@ export default function DetailDiscussionGeneral() {
const response = await apiSendDiscussionGeneralCommentar({ id: id, data: { desc: komentar, user: hasil } })
if (response.success) {
setKomentar('')
handleLoad('komentar')
handleLoad('komentar', false)
}
}
} catch (error) {
@@ -93,45 +115,57 @@ export default function DetailDiscussionGeneral() {
<View style={{ flex: 1 }}>
<ScrollView>
<View style={[Styles.p15, Styles.mb100]}>
<BorderBottomItem
borderType="bottom"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialIcons name="chat" size={25} color={'#384288'} />
</View>
}
title={data?.title}
subtitle={
!data?.isActive ?
<LabelStatus category='warning' text='ARSIP' size="small" />
:
<LabelStatus category={data.status == 1 ? 'success' : 'error'} text={data.status == 1 ? 'BUKA' : 'TUTUP'} size="small" />
}
rightTopInfo={data?.createdAt}
desc={data?.desc}
leftBottomInfo={
<View style={[Styles.rowItemsCenter]}>
<Ionicons name="chatbox-ellipses-outline" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation, Styles.cGray, Styles.mb05]}>{dataKomentar.length} Komentar</Text>
</View>
}
/>
{
loading ?
<SkeletonContent />
:
<BorderBottomItem
borderType="bottom"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialIcons name="chat" size={25} color={'#384288'} />
</View>
}
title={data?.title}
subtitle={
!data?.isActive ?
<LabelStatus category='warning' text='ARSIP' size="small" />
:
<LabelStatus category={data.status == 1 ? 'success' : 'error'} text={data.status == 1 ? 'BUKA' : 'TUTUP'} size="small" />
}
rightTopInfo={data?.createdAt}
desc={data?.desc}
leftBottomInfo={
<View style={[Styles.rowItemsCenter]}>
<Ionicons name="chatbox-ellipses-outline" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation, Styles.cGray, Styles.mb05]}>{dataKomentar.length} Komentar</Text>
</View>
}
/>
}
<View style={[Styles.p15]}>
{
dataKomentar.map((item, i) => {
return (
<BorderBottomItem
key={i}
borderType="bottom"
icon={
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} size="xs" />
}
title={item.username}
rightTopInfo={item.createdAt}
desc={item.comment}
/>
)
})
loadingKomentar ?
arrSkeleton.map((item: any, i: number) => {
return (
<Skeleton key={i} width={100} widthType="percent" height={40} borderRadius={5} />
)
})
:
dataKomentar.map((item, i) => {
return (
<BorderBottomItem
key={i}
borderType="bottom"
icon={
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} size="xs" />
}
title={item.username}
rightTopInfo={item.createdAt}
desc={item.comment}
/>
)
})
}
</View>
</View>

View File

@@ -2,6 +2,7 @@ import BorderBottomItem from "@/components/borderBottomItem";
import ButtonTab from "@/components/buttonTab";
import InputSearch from "@/components/inputSearch";
import LabelStatus from "@/components/labelStatus";
import SkeletonContent from "@/components/skeletonContent";
import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { apiGetDiscussionGeneral } from "@/lib/api";
@@ -30,21 +31,30 @@ export default function Discussion() {
const [nameGroup, setNameGroup] = useState('')
const [data, setData] = useState<Props[]>([])
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
const [loading, setLoading] = useState(true)
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
async function handleLoad() {
async function handleLoad(loading: boolean) {
try {
setLoading(loading)
const hasil = await decryptToken(String(token?.current))
const response = await apiGetDiscussionGeneral({ user: hasil, active: String(active), search: search, group: String(group) })
setData(response.data)
setNameGroup(response.filter.name)
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
useEffect(() => {
handleLoad()
}, [active, search, group, update])
handleLoad(true)
}, [active, search, group])
useEffect(() => {
handleLoad(false)
}, [update])
return (
<SafeAreaView>
@@ -75,37 +85,45 @@ export default function Discussion() {
}
<View>
{
data.length > 0
?
data.map((item: any, i: number) => {
loading ?
arrSkeleton.map((item: any, i: number) => {
return (
<BorderBottomItem
key={i}
onPress={() => { router.push(`/discussion/${item.id}`) }}
borderType="bottom"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialIcons name="chat" size={25} color={'#384288'} />
</View>
}
title={item.title}
subtitle={
active != "false" && <LabelStatus category={item.status === 1 ? "success" : "error"} text={item.status === 1 ? "BUKA" : "TUTUP"} size="small" />
}
rightTopInfo={item.createdAt}
desc={item.desc}
leftBottomInfo={
<View style={[Styles.rowItemsCenter]}>
<Ionicons name="chatbox-ellipses-outline" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation, Styles.cGray, Styles.mb05]}>Diskusikan</Text>
</View>
}
rightBottomInfo={`${item.total_komentar} Komentar`}
/>
<SkeletonContent key={i} />
)
})
:
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
data.length > 0
?
data.map((item: any, i: number) => {
return (
<BorderBottomItem
key={i}
onPress={() => { router.push(`/discussion/${item.id}`) }}
borderType="bottom"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialIcons name="chat" size={25} color={'#384288'} />
</View>
}
title={item.title}
subtitle={
active != "false" && <LabelStatus category={item.status === 1 ? "success" : "error"} text={item.status === 1 ? "BUKA" : "TUTUP"} size="small" />
}
rightTopInfo={item.createdAt}
desc={item.desc}
leftBottomInfo={
<View style={[Styles.rowItemsCenter]}>
<Ionicons name="chatbox-ellipses-outline" size={18} color="grey" style={Styles.mr05} />
<Text style={[Styles.textInformation, Styles.cGray, Styles.mb05]}>Diskusikan</Text>
</View>
}
rightBottomInfo={`${item.total_komentar} Komentar`}
/>
)
})
:
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
}
</View>
</View>

View File

@@ -4,6 +4,7 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
import DrawerBottom from "@/components/drawerBottom";
import ImageUser from "@/components/imageNew";
import MenuItemRow from "@/components/menuItemRow";
import SkeletonTwoItem from "@/components/skeletonTwoItem";
import { ColorsStatus } from "@/constants/ColorsStatus";
import Styles from "@/constants/Styles";
import { apiDeleteMemberDiscussionGeneral, apiGetDiscussionGeneralOne } from "@/lib/api";
@@ -28,28 +29,37 @@ export default function MemberDiscussionDetail() {
const [isModal, setModal] = useState(false)
const [chooseUser, setChooseUser] = useState({ idUser: '', name: '', img: '' })
const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
const [loading, setLoading] = useState(true)
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
async function handleLoad() {
async function handleLoad(loading: boolean) {
try {
setLoading(loading)
const hasil = await decryptToken(String(token?.current))
const response = await apiGetDiscussionGeneralOne({ id: id, user: hasil, cat: 'anggota' })
setData(response.data)
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
useEffect(() => {
handleLoad(false)
}, [update]);
useEffect(() => {
handleLoad()
}, [update]);
handleLoad(true)
}, []);
async function handleDeleteUser() {
try {
const hasil = await decryptToken(String(token?.current))
await apiDeleteMemberDiscussionGeneral({ user: hasil, idUser: chooseUser.idUser }, id)
ToastAndroid.show("Berhasil mengelluarkan anggota dari diskusi", ToastAndroid.SHORT)
handleLoad()
ToastAndroid.show("Berhasil mengeluarkan anggota dari diskusi", ToastAndroid.SHORT)
handleLoad(false)
} catch (error) {
console.error(error)
} finally {
@@ -84,22 +94,29 @@ export default function MemberDiscussionDetail() {
/>
}
{
data.map((item, index) => {
return (
<BorderBottomItem
key={index}
borderType="bottom"
icon={
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} size="sm" />
}
title={item.name}
onPress={() => {
setChooseUser(item)
setModal(true)
}}
/>
)
})
loading ?
arrSkeleton.map((item, index) => {
return (
<SkeletonTwoItem key={index} />
)
})
:
data.map((item, index) => {
return (
<BorderBottomItem
key={index}
borderType="bottom"
icon={
<ImageUser src={`https://wibu-storage.wibudev.com/api/files/${item.img}`} size="sm" />
}
title={item.name}
onPress={() => {
setChooseUser(item)
setModal(true)
}}
/>
)
})
}
</View>
</View>