feat: terapkan design baru pada halaman create project dan create task divisi
- Ganti file list (BorderBottomItem) dengan fileGrid/fileCard bergaya baru dengan icon berwarna sesuai tipe file - Ganti member section dengan card individual per anggota (avatar + nama + badge jabatan) - Header anggota: label kiri + jumlah orang di kanan - Simpan field position saat memilih anggota di modalSelect - Hapus wrapper wrapPaper di SectionListAddTask Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
@@ -21,11 +20,31 @@ import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
|
||||
import * as DocumentPicker from "expo-document-picker";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SafeAreaView, ScrollView, View } from "react-native";
|
||||
import { Pressable, SafeAreaView, ScrollView, View } from "react-native";
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
|
||||
function getFileIcon(ext: string): keyof typeof MaterialCommunityIcons.glyphMap {
|
||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return 'image-outline'
|
||||
if (ext === 'pdf') return 'file-pdf-box'
|
||||
if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return 'video-outline'
|
||||
if (['doc', 'docx'].includes(ext)) return 'file-word-outline'
|
||||
if (['xls', 'xlsx'].includes(ext)) return 'file-excel-outline'
|
||||
if (['zip', 'rar', '7z'].includes(ext)) return 'zip-box-outline'
|
||||
return 'file-outline'
|
||||
}
|
||||
|
||||
function getFileColor(ext: string): string {
|
||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return '#339AF0'
|
||||
if (ext === 'pdf') return '#F03E3E'
|
||||
if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return '#AE3EC9'
|
||||
if (['doc', 'docx'].includes(ext)) return '#1C7ED6'
|
||||
if (['xls', 'xlsx'].includes(ext)) return '#2F9E44'
|
||||
if (['zip', 'rar', '7z'].includes(ext)) return '#E8590C'
|
||||
return '#868E96'
|
||||
}
|
||||
|
||||
export default function CreateTaskDivision() {
|
||||
const { colors } = useTheme();
|
||||
const { id } = useLocalSearchParams();
|
||||
@@ -172,52 +191,74 @@ export default function CreateTaskDivision() {
|
||||
<ButtonSelect value="Upload File" onPress={pickDocumentAsync} />
|
||||
<ButtonSelect value="Tambah Anggota" onPress={() => { router.push(`/division/${id}/task/create/member`); }} />
|
||||
<SectionListAddTask />
|
||||
{
|
||||
fileForm.length > 0 && (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
{
|
||||
fileForm.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="all"
|
||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color={colors.text} />}
|
||||
title={item.name}
|
||||
titleWeight="normal"
|
||||
onPress={() => { setIndexDelFile(index); setModal(true) }}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
{fileForm.length > 0 && (
|
||||
<View style={Styles.mb15}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||
<View style={Styles.fileGrid}>
|
||||
{fileForm.map((item, index) => {
|
||||
const ext = item.name.split('.').pop()?.toLowerCase() ?? ''
|
||||
const baseName = item.name.includes('.') ? item.name.split('.').slice(0, -1).join('.') : item.name
|
||||
const iconName = getFileIcon(ext)
|
||||
const iconColor = getFileColor(ext)
|
||||
return (
|
||||
<Pressable
|
||||
key={index}
|
||||
onPress={() => { setIndexDelFile(index); setModal(true) }}
|
||||
style={[Styles.fileCard, { backgroundColor: colors.card, borderColor: colors.icon + '18' }]}
|
||||
>
|
||||
<View style={[Styles.sectionIconBox, { backgroundColor: iconColor + '20' }]}>
|
||||
<MaterialCommunityIcons name={iconName} size={18} color={iconColor} />
|
||||
</View>
|
||||
<View style={Styles.flex1}>
|
||||
<Text style={Styles.textDefault} numberOfLines={1}>{baseName}</Text>
|
||||
<Text style={[Styles.textSmallSemiBold, { color: colors.dimmed }]}>
|
||||
{ext.toUpperCase()}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
)}
|
||||
{entitiesMember.length > 0 && (
|
||||
<View>
|
||||
<View style={Styles.mb15}>
|
||||
<View style={[Styles.rowSpaceBetween, Styles.mv05]}>
|
||||
<Text>Anggota</Text>
|
||||
<Text>Total {entitiesMember.length} Anggota</Text>
|
||||
<Text style={Styles.textDefaultSemiBold}>Anggota</Text>
|
||||
<Text style={[Styles.textDefault, { color: colors.dimmed }]}>{entitiesMember.length} orang</Text>
|
||||
</View>
|
||||
|
||||
<View style={[Styles.borderAll, Styles.round05, Styles.p10, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
{entitiesMember.map(
|
||||
(item: { img: any; name: any }, index: any) => {
|
||||
return (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<ImageUser
|
||||
src={`${ConstEnv.url_storage}/files/${item.img}`}
|
||||
size="sm"
|
||||
/>
|
||||
}
|
||||
title={item.name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
<View style={{ gap: 6 }}>
|
||||
{entitiesMember.map((item: { img: any; name: any; position?: string }, index: any) => (
|
||||
<View
|
||||
key={index}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: colors.card,
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.icon + '18',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} size="xs" />
|
||||
<Text style={[Styles.textDefault, Styles.flex1, { color: colors.text }]} numberOfLines={1}>{item.name}</Text>
|
||||
{item.position && (
|
||||
<View style={{
|
||||
backgroundColor: colors.dimmed + '15',
|
||||
borderRadius: 20,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
}}>
|
||||
<Text style={[Styles.textSmallSemiBold, { color: colors.dimmed }]} numberOfLines={1}>
|
||||
{item.position}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import AppHeader from "@/components/AppHeader";
|
||||
import BorderBottomItem from "@/components/borderBottomItem";
|
||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||
import ButtonSelect from "@/components/buttonSelect";
|
||||
import DrawerBottom from "@/components/drawerBottom";
|
||||
@@ -25,6 +24,7 @@ import * as DocumentPicker from "expo-document-picker";
|
||||
import { router, Stack } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
Pressable,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
View
|
||||
@@ -32,6 +32,26 @@ import {
|
||||
import Toast from "react-native-toast-message";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
function getFileIcon(ext: string): keyof typeof MaterialCommunityIcons.glyphMap {
|
||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return 'image-outline'
|
||||
if (ext === 'pdf') return 'file-pdf-box'
|
||||
if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return 'video-outline'
|
||||
if (['doc', 'docx'].includes(ext)) return 'file-word-outline'
|
||||
if (['xls', 'xlsx'].includes(ext)) return 'file-excel-outline'
|
||||
if (['zip', 'rar', '7z'].includes(ext)) return 'zip-box-outline'
|
||||
return 'file-outline'
|
||||
}
|
||||
|
||||
function getFileColor(ext: string): string {
|
||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return '#339AF0'
|
||||
if (ext === 'pdf') return '#F03E3E'
|
||||
if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return '#AE3EC9'
|
||||
if (['doc', 'docx'].includes(ext)) return '#1C7ED6'
|
||||
if (['xls', 'xlsx'].includes(ext)) return '#2F9E44'
|
||||
if (['zip', 'rar', '7z'].includes(ext)) return '#E8590C'
|
||||
return '#868E96'
|
||||
}
|
||||
|
||||
export default function CreateProject() {
|
||||
const { colors } = useTheme();
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -300,52 +320,74 @@ export default function CreateProject() {
|
||||
errorText="Anggota tidak boleh kosong"
|
||||
/>
|
||||
<SectionListAddTask />
|
||||
{
|
||||
fileForm.length > 0 && (
|
||||
<View style={[Styles.mb15]}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.background }]}>
|
||||
{
|
||||
fileForm.map((item, index) => (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="all"
|
||||
icon={<MaterialCommunityIcons name="file-outline" size={25} color={colors.text} />}
|
||||
title={item.name}
|
||||
titleWeight="normal"
|
||||
onPress={() => { setIndexDelFile(index); setModal(true) }}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</View>
|
||||
{fileForm.length > 0 && (
|
||||
<View style={Styles.mb15}>
|
||||
<Text style={[Styles.textDefaultSemiBold, Styles.mv05]}>File</Text>
|
||||
<View style={Styles.fileGrid}>
|
||||
{fileForm.map((item, index) => {
|
||||
const ext = item.name.split('.').pop()?.toLowerCase() ?? ''
|
||||
const baseName = item.name.includes('.') ? item.name.split('.').slice(0, -1).join('.') : item.name
|
||||
const iconName = getFileIcon(ext)
|
||||
const iconColor = getFileColor(ext)
|
||||
return (
|
||||
<Pressable
|
||||
key={index}
|
||||
onPress={() => { setIndexDelFile(index); setModal(true) }}
|
||||
style={[Styles.fileCard, { backgroundColor: colors.card, borderColor: colors.icon + '18' }]}
|
||||
>
|
||||
<View style={[Styles.sectionIconBox, { backgroundColor: iconColor + '20' }]}>
|
||||
<MaterialCommunityIcons name={iconName} size={18} color={iconColor} />
|
||||
</View>
|
||||
<View style={Styles.flex1}>
|
||||
<Text style={Styles.textDefault} numberOfLines={1}>{baseName}</Text>
|
||||
<Text style={[Styles.textSmallSemiBold, { color: colors.dimmed }]}>
|
||||
{ext.toUpperCase()}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
)}
|
||||
{entitiesMember.length > 0 && (
|
||||
<View>
|
||||
<View style={Styles.mb15}>
|
||||
<View style={[Styles.rowSpaceBetween, Styles.mv05]}>
|
||||
<Text>Anggota</Text>
|
||||
<Text>Total {entitiesMember.length} Anggota</Text>
|
||||
<Text style={Styles.textDefaultSemiBold}>Anggota</Text>
|
||||
<Text style={[Styles.textDefault, { color: colors.dimmed }]}>{entitiesMember.length} orang</Text>
|
||||
</View>
|
||||
|
||||
<View style={[Styles.borderAll, Styles.round05, Styles.p10, { borderColor: colors.icon + '20', backgroundColor: colors.card }]}>
|
||||
{entitiesMember.map(
|
||||
(item: { img: any; name: any }, index: any) => {
|
||||
return (
|
||||
<BorderBottomItem
|
||||
key={index}
|
||||
borderType="bottom"
|
||||
icon={
|
||||
<ImageUser
|
||||
src={`${ConstEnv.url_storage}/files/${item.img}`}
|
||||
size="sm"
|
||||
/>
|
||||
}
|
||||
title={item.name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
<View style={{ gap: 6 }}>
|
||||
{entitiesMember.map((item: { img: any; name: any; position?: string }, index: any) => (
|
||||
<View
|
||||
key={index}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: colors.card,
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.icon + '18',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} size="xs" />
|
||||
<Text style={[Styles.textDefault, Styles.flex1, { color: colors.text }]} numberOfLines={1}>{item.name}</Text>
|
||||
{item.position && (
|
||||
<View style={{
|
||||
backgroundColor: colors.dimmed + '15',
|
||||
borderRadius: 20,
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
}}>
|
||||
<Text style={[Styles.textSmallSemiBold, { color: colors.dimmed }]} numberOfLines={1}>
|
||||
{item.position}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user