Compare commits
7 Commits
resourcing
...
resourcing
| Author | SHA1 | Date | |
|---|---|---|---|
| 71ea0ca5f2 | |||
| ee7efaef6a | |||
| bfb029058c | |||
| b7e774a556 | |||
| 2901d19db0 | |||
| 5c4dadbe7c | |||
| 6ac122c631 |
2
app.json
2
app.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "hipmi-mobile",
|
||||
"name": "HIPMI BADUNG",
|
||||
"slug": "hipmi-mobile",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Profile */}
|
||||
{/* ========== Profile Section ========= */}
|
||||
<Stack.Screen
|
||||
name="profile"
|
||||
options={{
|
||||
@@ -40,15 +40,15 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Portofolio */}
|
||||
{/* ========== Portofolio Section ========= */}
|
||||
<Stack.Screen
|
||||
name="portofolio"
|
||||
options={{
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* User Search */}
|
||||
|
||||
{/* ========== User Search Section ========= */}
|
||||
<Stack.Screen
|
||||
name="user-search/index"
|
||||
options={{
|
||||
@@ -57,7 +57,7 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Notification */}
|
||||
{/* ========== Notification Section ========= */}
|
||||
<Stack.Screen
|
||||
name="notifications/index"
|
||||
options={{
|
||||
@@ -66,7 +66,7 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Event */}
|
||||
{/* ========== Event Section ========= */}
|
||||
<Stack.Screen
|
||||
name="event/(tabs)"
|
||||
options={{
|
||||
@@ -85,7 +85,7 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Forum */}
|
||||
{/* ========== Forum Section ========= */}
|
||||
<Stack.Screen
|
||||
name="forum/index"
|
||||
options={{
|
||||
@@ -94,7 +94,7 @@ export default function UserLayout() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Maps */}
|
||||
{/* ========== Maps Section ========= */}
|
||||
<Stack.Screen
|
||||
name="maps/index"
|
||||
options={{
|
||||
@@ -102,8 +102,29 @@ export default function UserLayout() {
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="maps/create"
|
||||
options={{
|
||||
title: "Tambah Maps",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="maps/[id]/edit"
|
||||
options={{
|
||||
title: "Edit Maps",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="maps/[id]/custom-pin"
|
||||
options={{
|
||||
title: "Custom Pin Maps",
|
||||
headerLeft: () => <BackButton />,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Marketplace */}
|
||||
{/* ========== Marketplace Section ========= */}
|
||||
<Stack.Screen
|
||||
name="marketplace/index"
|
||||
options={{
|
||||
|
||||
11
app/(application)/(user)/maps/[id]/custom-pin.tsx
Normal file
11
app/(application)/(user)/maps/[id]/custom-pin.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
|
||||
export default function MapsCustomPin() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<TextCustom>Maps Custom Pin</TextCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
11
app/(application)/(user)/maps/[id]/edit.tsx
Normal file
11
app/(application)/(user)/maps/[id]/edit.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
|
||||
export default function MapsEdit() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<TextCustom>Maps Edit</TextCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
59
app/(application)/(user)/maps/create.tsx
Normal file
59
app/(application)/(user)/maps/create.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
BaseBox,
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
InformationBox,
|
||||
LandscapeFrameUploaded,
|
||||
Spacing,
|
||||
TextCustom,
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
|
||||
export default function MapsCreate() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const buttonFooter = (
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
console.log("Simpan");
|
||||
router.replace(`/portofolio/${id}`);
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
);
|
||||
return (
|
||||
<ViewWrapper footerComponent={buttonFooter}>
|
||||
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
||||
|
||||
<BaseBox style={{ height: 400 }}>
|
||||
<TextCustom>Maps Her</TextCustom>
|
||||
</BaseBox>
|
||||
|
||||
<TextInputCustom
|
||||
required
|
||||
label="Nama Pin"
|
||||
placeholder="Masukkan nama pin maps"
|
||||
/>
|
||||
|
||||
<Spacing height={50} />
|
||||
|
||||
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
||||
<LandscapeFrameUploaded />
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => {
|
||||
console.log("Upload foto ");
|
||||
router.navigate(`/take-picture/${id}`);
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</ButtonCenteredOnly>
|
||||
<Spacing height={50} />
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
Grid,
|
||||
InformationBox,
|
||||
LandscapeFrameUploaded,
|
||||
SelectCustom,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
@@ -10,15 +13,11 @@ import {
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
|
||||
import InformationBox from "@/components/Box/InformationBox";
|
||||
import ButtonCenteredOnly from "@/components/Button/ButtonCenteredOnly";
|
||||
import LandscapeFrameUploaded from "@/components/Image/LandscapeFrameUploaded";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis";
|
||||
import dummyMasterSubBidangBisnis from "@/lib/dummy-data/master-sub-bidang-bisnis";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import { Text, TouchableOpacity, View } from "react-native";
|
||||
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
||||
@@ -45,7 +44,8 @@ export default function PortofolioCreate() {
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
console.log("save");
|
||||
console.log("Selanjutnya");
|
||||
router.replace(`/maps/create`);
|
||||
}
|
||||
|
||||
const buttonSave = (
|
||||
@@ -57,12 +57,13 @@ export default function PortofolioCreate() {
|
||||
return (
|
||||
<ViewWrapper footerComponent={buttonSave}>
|
||||
{/* <TextCustom>Portofolio Create {id}</TextCustom> */}
|
||||
<StackCustom>
|
||||
<StackCustom gap={"xs"}>
|
||||
<InformationBox text="Lengkapi data bisnis anda." />
|
||||
<TextInputCustom
|
||||
required
|
||||
label="Nama Bisnis"
|
||||
placeholder="Masukkan nama bisnis"
|
||||
|
||||
/>
|
||||
<SelectCustom
|
||||
label="Bidang Usaha"
|
||||
@@ -71,20 +72,26 @@ export default function PortofolioCreate() {
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))}
|
||||
value=""
|
||||
onChange={(value) => console.log(value)}
|
||||
value={data.bidang_usaha}
|
||||
onChange={(value) => {
|
||||
setData({ ...(data as any), bidang_usaha: value });
|
||||
}}
|
||||
/>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={10}>
|
||||
<SelectCustom
|
||||
// disabled
|
||||
label="Sub Bidang Usaha"
|
||||
required
|
||||
data={dummyMasterSubBidangBisnis.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))}
|
||||
value=""
|
||||
onChange={(value) => console.log(value)}
|
||||
value={data.sub_bidang_usaha}
|
||||
onChange={(value) => {
|
||||
setData({ ...(data as any), sub_bidang_usaha: value });
|
||||
}}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col
|
||||
@@ -96,15 +103,12 @@ export default function PortofolioCreate() {
|
||||
</TouchableOpacity>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
<ButtonCenteredOnly onPress={() => console.log("add")}>
|
||||
Tambah Pilihan
|
||||
</ButtonCenteredOnly>
|
||||
<Spacing />
|
||||
<TextInputCustom
|
||||
required
|
||||
label="Alamat Bisnis"
|
||||
placeholder="Masukkan alamat bisnis"
|
||||
/>
|
||||
|
||||
<View>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<TextCustom semiBold style={{ color: MainColor.white_gray }}>
|
||||
@@ -123,6 +127,13 @@ export default function PortofolioCreate() {
|
||||
/>
|
||||
</View>
|
||||
<Spacing />
|
||||
|
||||
<TextInputCustom
|
||||
required
|
||||
label="Alamat Bisnis"
|
||||
placeholder="Masukkan alamat bisnis"
|
||||
/>
|
||||
|
||||
<TextAreaCustom
|
||||
label="Deskripsi Bisnis"
|
||||
placeholder="Masukkan deskripsi bisnis"
|
||||
@@ -136,12 +147,22 @@ export default function PortofolioCreate() {
|
||||
maxLength={100}
|
||||
/>
|
||||
<Spacing />
|
||||
|
||||
{/* Logo */}
|
||||
<InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." />
|
||||
<LandscapeFrameUploaded />
|
||||
<ButtonCenteredOnly icon="upload" onPress={() => console.log("upload")}>
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => {
|
||||
console.log("Upload logo >>", id);
|
||||
router.navigate(`/(application)/take-picture/${id}`);
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</ButtonCenteredOnly>
|
||||
<Spacing height={40} />
|
||||
|
||||
{/* Social Media */}
|
||||
<InformationBox text="Isi hanya pada sosial media yang anda miliki." />
|
||||
<TextInputCustom
|
||||
label="Tiktok"
|
||||
|
||||
11
app/(application)/(user)/portofolio/[id]/edit-logo.tsx
Normal file
11
app/(application)/(user)/portofolio/[id]/edit-logo.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
|
||||
export default function PortofolioEditLogo() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<TextCustom>Portofolio Edit Logo</TextCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
|
||||
export default function PortofolioEditSocialMedia() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<TextCustom>Portofolio Edit Social Media</TextCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
11
app/(application)/(user)/portofolio/[id]/edit.tsx
Normal file
11
app/(application)/(user)/portofolio/[id]/edit.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
|
||||
export default function PortofolioEdit() {
|
||||
return (
|
||||
<>
|
||||
<ViewWrapper>
|
||||
<TextCustom>Portofolio Edit</TextCustom>
|
||||
</ViewWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,32 +1,63 @@
|
||||
import { DrawerCustom } from "@/components";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { drawerItemsPortofolio } from "@/screens/Portofolio/ListPage";
|
||||
import Portofolio_MenuDrawerSection from "@/screens/Portofolio/MenuDrawer";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Stack, useLocalSearchParams } from "expo-router";
|
||||
import { Text } from "react-native";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Text,
|
||||
TouchableOpacity
|
||||
} from "react-native";
|
||||
|
||||
export default function Portofolio() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const { id } = useLocalSearchParams();
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
|
||||
const openDrawer = () => {
|
||||
setIsDrawerOpen(true);
|
||||
};
|
||||
const closeDrawer = () => {
|
||||
setIsDrawerOpen(false);
|
||||
};
|
||||
return (
|
||||
<ViewWrapper>
|
||||
{/* Header */}
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: "Portofolio",
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
// headerRight: () => (
|
||||
// <TouchableOpacity onPress={openDrawer}>
|
||||
// <Ionicons
|
||||
// name="ellipsis-vertical"
|
||||
// size={20}
|
||||
// color={MainColor.yellow}
|
||||
// />
|
||||
// </TouchableOpacity>
|
||||
// ),
|
||||
headerStyle: GStyles.headerStyle,
|
||||
headerTitleStyle: GStyles.headerTitleStyle,
|
||||
}}
|
||||
/>
|
||||
<Text style={GStyles.textLabel}>Portofolio {id}</Text>
|
||||
</ViewWrapper>
|
||||
<>
|
||||
<ViewWrapper>
|
||||
{/* Header */}
|
||||
<Stack.Screen
|
||||
options={{
|
||||
title: "Portofolio",
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
headerRight: () => (
|
||||
<TouchableOpacity onPress={openDrawer}>
|
||||
<Ionicons
|
||||
name="ellipsis-vertical"
|
||||
size={20}
|
||||
color={MainColor.yellow}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
),
|
||||
headerStyle: GStyles.headerStyle,
|
||||
headerTitleStyle: GStyles.headerTitleStyle,
|
||||
}}
|
||||
/>
|
||||
<Text style={GStyles.textLabel}>Portofolio {id}</Text>
|
||||
</ViewWrapper>
|
||||
|
||||
{/* Drawer Komponen Eksternal */}
|
||||
<DrawerCustom
|
||||
isVisible={isDrawerOpen}
|
||||
closeDrawer={closeDrawer}
|
||||
height={350}
|
||||
>
|
||||
<Portofolio_MenuDrawerSection
|
||||
drawerItems={drawerItemsPortofolio({ id: id as string })}
|
||||
setIsDrawerOpen={setIsDrawerOpen}
|
||||
/>
|
||||
</DrawerCustom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
47
app/(application)/(user)/portofolio/[id]/list.tsx
Normal file
47
app/(application)/(user)/portofolio/[id]/list.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { BaseBox, Grid, TextCustom, ViewWrapper } from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
|
||||
export default function ListPortofolio() {
|
||||
const { id } = useLocalSearchParams();
|
||||
return (
|
||||
<ViewWrapper>
|
||||
{Array.from({ length: 10 }).map((_, index) => (
|
||||
<BaseBox
|
||||
key={index}
|
||||
style={{ backgroundColor: MainColor.darkblue }}
|
||||
onPress={() => {
|
||||
console.log("press to Portofolio");
|
||||
router.push(`/portofolio/${id}`);
|
||||
}}
|
||||
>
|
||||
<Grid>
|
||||
<Grid.Col
|
||||
span={10}
|
||||
style={{ justifyContent: "center", backgroundColor: "" }}
|
||||
>
|
||||
<TextCustom bold size="large" truncate={1}>
|
||||
Nama usaha portofolio
|
||||
</TextCustom>
|
||||
<TextCustom size="small" color="yellow">
|
||||
#id-porofolio12345
|
||||
</TextCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col
|
||||
span={2}
|
||||
style={{ alignItems: "flex-end", justifyContent: "center" }}
|
||||
>
|
||||
<Ionicons
|
||||
name="caret-forward"
|
||||
size={ICON_SIZE_SMALL}
|
||||
color="white"
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</BaseBox>
|
||||
))}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { HeaderStyles } from "@/styles/header-styles";
|
||||
import { Stack } from "expo-router";
|
||||
|
||||
export default function PortofolioLayout() {
|
||||
@@ -8,10 +7,7 @@ export default function PortofolioLayout() {
|
||||
<>
|
||||
<Stack
|
||||
screenOptions={{
|
||||
headerStyle: GStyles.headerStyle,
|
||||
headerTitleStyle: GStyles.headerTitleStyle,
|
||||
headerTitleAlign: "center",
|
||||
headerBackButtonDisplayMode: "minimal",
|
||||
...HeaderStyles,
|
||||
headerLeft: () => <LeftButtonCustom />,
|
||||
}}
|
||||
>
|
||||
@@ -20,7 +16,16 @@ export default function PortofolioLayout() {
|
||||
name="[id]/create"
|
||||
options={{ title: "Tambah Portofolio" }}
|
||||
/>
|
||||
|
||||
<Stack.Screen
|
||||
name="[id]/list"
|
||||
options={{ title: "Daftar Portofolio" }}
|
||||
/>
|
||||
<Stack.Screen name="[id]/edit" options={{ title: "Edit Portofolio" }} />
|
||||
<Stack.Screen name="[id]/edit-logo" options={{ title: "Edit Logo " }} />
|
||||
<Stack.Screen
|
||||
name="[id]/edit-social-media"
|
||||
options={{ title: "Edit Social Media" }}
|
||||
/>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
AvatarCustom,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
SelectCustom,
|
||||
Spacing,
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
} from "@/components";
|
||||
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
|
||||
import InformationBox from "@/components/Box/InformationBox";
|
||||
import ButtonUpload from "@/components/Button/ButtonUpload";
|
||||
import LandscapeFrameUploaded from "@/components/Image/LandscapeFrameUploaded";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { useState } from "react";
|
||||
@@ -47,9 +47,12 @@ export default function CreateProfile() {
|
||||
<View style={{ alignItems: "center" }}>
|
||||
<AvatarCustom size="xl" />
|
||||
<Spacing />
|
||||
<ButtonUpload
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => router.navigate(`/take-picture/${id}`)}
|
||||
/>
|
||||
>
|
||||
Upload
|
||||
</ButtonCenteredOnly>
|
||||
</View>
|
||||
|
||||
<Spacing />
|
||||
@@ -58,9 +61,12 @@ export default function CreateProfile() {
|
||||
<InformationBox text="Upload foto latar belakang anda." />
|
||||
<LandscapeFrameUploaded />
|
||||
<Spacing />
|
||||
<ButtonUpload
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => router.navigate(`/take-picture/${id}`)}
|
||||
/>
|
||||
>
|
||||
Upload
|
||||
</ButtonCenteredOnly>
|
||||
</View>
|
||||
|
||||
<Spacing />
|
||||
|
||||
@@ -1,79 +1,28 @@
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import AlertCustom from "@/components/Alert/AlertCustom";
|
||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||
import DrawerCustom from "@/components/Drawer/DrawerCustom";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { DRAWER_HEIGHT } from "@/constants/constans-value";
|
||||
import { drawerItemsProfile } from "@/screens/Profile/ListPage";
|
||||
import Profile_MenuDrawerSection from "@/screens/Profile/MenuDrawerSection";
|
||||
import ProfilSection from "@/screens/Profile/ProfilSection";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Animated, InteractionManager, TouchableOpacity } from "react-native";
|
||||
import React, { useState } from "react";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
|
||||
export default function Profile() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
const [showLogoutAlert, setShowLogoutAlert] = useState(false);
|
||||
|
||||
const drawerItems: IMenuDrawerItem[] = [
|
||||
{
|
||||
icon: "create",
|
||||
label: "Edit profile",
|
||||
path: `/(application)/profile/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: "camera",
|
||||
label: "Ubah foto profile",
|
||||
path: `/(application)/profile/${id}/update-photo`,
|
||||
},
|
||||
{
|
||||
icon: "image",
|
||||
label: "Ubah latar belakang",
|
||||
path: `/(application)/profile/${id}/update-background`,
|
||||
},
|
||||
{
|
||||
icon: "add-circle",
|
||||
label: "Tambah portofolio",
|
||||
path: `/(application)/portofolio/${id}/create`,
|
||||
},
|
||||
// {
|
||||
// icon: "settings",
|
||||
// label: "Dashboard Admin",
|
||||
// path: `/(application)/profile/dashboard-admin`,
|
||||
// },
|
||||
{ icon: "log-out", label: "Keluar", color: "red", path: "" },
|
||||
{
|
||||
icon: "create-outline",
|
||||
label: "Create profile",
|
||||
path: `/(application)/profile/${id}/create`,
|
||||
},
|
||||
];
|
||||
|
||||
// Animasi menggunakan translateY (lebih kompatibel)
|
||||
const drawerAnim = useRef(new Animated.Value(DRAWER_HEIGHT)).current; // mulai di luar bawah layar
|
||||
|
||||
const openDrawer = () => {
|
||||
setIsDrawerOpen(true);
|
||||
Animated.timing(drawerAnim, {
|
||||
toValue: 0,
|
||||
duration: 300,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
};
|
||||
|
||||
const closeDrawer = () => {
|
||||
Animated.timing(drawerAnim, {
|
||||
toValue: DRAWER_HEIGHT, // sesuaikan dengan tinggi drawer Anda
|
||||
duration: 300,
|
||||
useNativeDriver: true,
|
||||
}).start(() => {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
setIsDrawerOpen(false); // baru ganti state setelah animasi selesai
|
||||
});
|
||||
});
|
||||
setIsDrawerOpen(false);
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
@@ -104,18 +53,16 @@ export default function Profile() {
|
||||
}}
|
||||
/>
|
||||
<ProfilSection />
|
||||
|
||||
</ViewWrapper>
|
||||
|
||||
{/* Drawer Komponen Eksternal */}
|
||||
<DrawerCustom
|
||||
height={350}
|
||||
isVisible={isDrawerOpen}
|
||||
drawerAnim={drawerAnim}
|
||||
closeDrawer={closeDrawer}
|
||||
>
|
||||
<Profile_MenuDrawerSection
|
||||
drawerItems={drawerItems}
|
||||
drawerItems={drawerItemsProfile({ id: id as string })}
|
||||
setShowLogoutAlert={setShowLogoutAlert}
|
||||
setIsDrawerOpen={setIsDrawerOpen}
|
||||
/>
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
import { BaseBox, ButtonCustom } from "@/components";
|
||||
import {
|
||||
BaseBox,
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
} from "@/components";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import ButtonUpload from "@/components/Button/ButtonUpload";
|
||||
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { Image } from "react-native";
|
||||
|
||||
export default function UpdateBackgroundProfile() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const buttonFooter = (
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
console.log("Simpan foto background >>", id);
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
);
|
||||
|
||||
return (
|
||||
<ViewWrapper
|
||||
bottomBarComponent={
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
console.log("Simpan foto background >>", id);
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
}
|
||||
>
|
||||
<ViewWrapper footerComponent={buttonFooter}>
|
||||
<BaseBox
|
||||
style={{ alignItems: "center", justifyContent: "center", height: 250 }}
|
||||
>
|
||||
@@ -30,12 +36,12 @@ export default function UpdateBackgroundProfile() {
|
||||
/>
|
||||
</BaseBox>
|
||||
|
||||
<ButtonUpload
|
||||
title="Update"
|
||||
onPress={() =>
|
||||
router.navigate(`/(application)/take-picture/${id}`)
|
||||
}
|
||||
/>
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => router.navigate(`/(application)/take-picture/${id}`)}
|
||||
>
|
||||
Update
|
||||
</ButtonCenteredOnly>
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
import { BaseBox, ButtonCustom } from "@/components";
|
||||
import {
|
||||
BaseBox,
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
} from "@/components";
|
||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||
import ButtonUpload from "@/components/Button/ButtonUpload";
|
||||
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { Image } from "react-native";
|
||||
|
||||
export default function UpdatePhotoProfile() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const buttonFooter = (
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
console.log("Simpan foto profile >>", id);
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
);
|
||||
return (
|
||||
<ViewWrapper
|
||||
bottomBarComponent={
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
console.log("Simpan foto profile >>", id);
|
||||
router.back();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
}
|
||||
>
|
||||
<ViewWrapper footerComponent={buttonFooter}>
|
||||
<BaseBox
|
||||
style={{ alignItems: "center", justifyContent: "center", height: 250 }}
|
||||
>
|
||||
@@ -30,13 +35,18 @@ export default function UpdatePhotoProfile() {
|
||||
/>
|
||||
</BaseBox>
|
||||
|
||||
<ButtonUpload
|
||||
title="Update"
|
||||
<ButtonCenteredOnly
|
||||
icon="upload"
|
||||
onPress={() => {
|
||||
console.log("Update photo >>", id);
|
||||
router.navigate(`/(application)/take-picture/${id}`);
|
||||
}}
|
||||
/>
|
||||
>
|
||||
Update
|
||||
</ButtonCenteredOnly>
|
||||
|
||||
{/* <Spacing />
|
||||
<ButtonCustom>Test</ButtonCustom> */}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function TakePicture() {
|
||||
/>
|
||||
<Spacing />
|
||||
|
||||
<StackCustom>
|
||||
<StackCustom >
|
||||
<ButtonCustom onPress={() => setUri(null)} title="Foto ulang" />
|
||||
<ButtonCustom
|
||||
onPress={() => {
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
import React from "react";
|
||||
import { StyleProp, Text, TouchableOpacity, ViewStyle } from "react-native";
|
||||
import buttonStyles from "./buttonCustomStyles";
|
||||
import { radiusMap } from "@/constants/radius-value";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { stylesButton } from "./buttonCustomStyles";
|
||||
|
||||
// Import radiusMap
|
||||
|
||||
|
||||
// Definisi type untuk radius
|
||||
type RadiusType = keyof typeof radiusMap | number;
|
||||
|
||||
@@ -30,30 +29,29 @@ const ButtonCustom: React.FC<ButtonProps> = ({
|
||||
title = "Button",
|
||||
backgroundColor = MainColor.yellow,
|
||||
textColor = MainColor.black,
|
||||
radius = "full", // default md
|
||||
radius = 50, // default md
|
||||
disabled = false,
|
||||
iconLeft,
|
||||
style,
|
||||
}) => {
|
||||
const borderRadius =
|
||||
typeof radius === "number" ? radius : radiusMap[radius ?? "md"]; // fallback ke 'md'
|
||||
|
||||
const styles = buttonStyles({
|
||||
backgroundColor,
|
||||
textColor,
|
||||
borderRadius,
|
||||
});
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.button, disabled && styles.disabled, style]}
|
||||
style={[
|
||||
stylesButton.button,
|
||||
disabled && stylesButton.disabled,
|
||||
style,
|
||||
{ borderRadius: radius },
|
||||
{ backgroundColor },
|
||||
]}
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
{/* Render icon jika tersedia */}
|
||||
{iconLeft && iconLeft}
|
||||
<Text style={styles.buttonText}>{children || title}</Text>
|
||||
<Text style={[stylesButton.buttonText, { color: textColor }]}>
|
||||
{children || title}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import React from "react";
|
||||
import ButtonCustom from "./ButtonCustom";
|
||||
|
||||
interface ButtonUploadProps {
|
||||
title?: string;
|
||||
onPress: () => void;
|
||||
}
|
||||
export default function ButtonUpload({ onPress, title = "Upload" }: ButtonUploadProps) {
|
||||
return (
|
||||
<ButtonCustom
|
||||
onPress={onPress}
|
||||
iconLeft={<Feather name="upload" size={20} color={MainColor.black} />}
|
||||
style={GStyles.buttonCentered50Percent}
|
||||
>
|
||||
{title}
|
||||
</ButtonCustom>
|
||||
);
|
||||
}
|
||||
@@ -4,24 +4,18 @@ import { MainColor } from "@/constants/color-palet";
|
||||
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
export default function buttonStyles({
|
||||
backgroundColor = "#007AFF",
|
||||
textColor = "#FFFFFF",
|
||||
borderRadius = 8,
|
||||
}) {
|
||||
return StyleSheet.create({
|
||||
export const stylesButton = StyleSheet.create({
|
||||
button: {
|
||||
backgroundColor,
|
||||
backgroundColor: MainColor.yellow,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 20,
|
||||
borderRadius,
|
||||
flexDirection: "row", // 👈 Tambahkan baris ini
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
},
|
||||
buttonText: {
|
||||
color: textColor,
|
||||
color: MainColor.black,
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
fontWeight: "600",
|
||||
},
|
||||
@@ -29,4 +23,3 @@ export default function buttonStyles({
|
||||
backgroundColor: MainColor.disabled,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useRef } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import {
|
||||
Animated,
|
||||
InteractionManager,
|
||||
PanResponder,
|
||||
StyleSheet,
|
||||
View,
|
||||
Animated,
|
||||
PanResponder,
|
||||
StyleSheet,
|
||||
View,
|
||||
InteractionManager,
|
||||
} from "react-native";
|
||||
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
@@ -14,7 +14,7 @@ interface DrawerCustomProps {
|
||||
children?: React.ReactNode;
|
||||
height?: number;
|
||||
isVisible: boolean;
|
||||
drawerAnim: Animated.Value;
|
||||
drawerAnim?: Animated.Value;
|
||||
closeDrawer: () => void;
|
||||
// openLogoutAlert: () => void;
|
||||
}
|
||||
@@ -33,6 +33,26 @@ export default function DrawerCustom({
|
||||
closeDrawer,
|
||||
}: // openLogoutAlert,
|
||||
DrawerCustomProps) {
|
||||
const drawerAnima = useRef(
|
||||
new Animated.Value(height || DRAWER_HEIGHT)
|
||||
).current;
|
||||
// Efek untuk handle open/close drawer
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
Animated.timing(drawerAnima, {
|
||||
toValue: 0,
|
||||
duration: 300,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
} else {
|
||||
Animated.timing(drawerAnima, {
|
||||
toValue: height || DRAWER_HEIGHT,
|
||||
duration: 300,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}
|
||||
}, [isVisible, drawerAnim, height, closeDrawer, drawerAnima]);
|
||||
|
||||
const panResponder = useRef(
|
||||
PanResponder.create({
|
||||
onMoveShouldSetPanResponder: (_, gestureState) => {
|
||||
@@ -41,7 +61,7 @@ DrawerCustomProps) {
|
||||
onPanResponderMove: (_, gestureState) => {
|
||||
const offset = gestureState.dy;
|
||||
if (offset >= 0 && offset <= DRAWER_HEIGHT) {
|
||||
drawerAnim.setValue(offset);
|
||||
drawerAnima.setValue(offset);
|
||||
}
|
||||
},
|
||||
onPanResponderRelease: (_, gestureState) => {
|
||||
@@ -50,7 +70,7 @@ DrawerCustomProps) {
|
||||
closeDrawer();
|
||||
});
|
||||
} else {
|
||||
Animated.spring(drawerAnim, {
|
||||
Animated.spring(drawerAnima, {
|
||||
toValue: 0,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
@@ -80,13 +100,13 @@ DrawerCustomProps) {
|
||||
styles.drawer,
|
||||
{
|
||||
height: height || DRAWER_HEIGHT,
|
||||
transform: [{ translateY: drawerAnim }],
|
||||
transform: [{ translateY: drawerAnima }],
|
||||
},
|
||||
]}
|
||||
{...panResponder.panHandlers}
|
||||
>
|
||||
<View
|
||||
style={[styles.headerBar, { backgroundColor: MainColor.white_gray }]}
|
||||
style={[styles.headerBar, { backgroundColor: MainColor.white }]}
|
||||
/>
|
||||
|
||||
{children}
|
||||
@@ -152,7 +172,7 @@ const styles = StyleSheet.create({
|
||||
headerBar: {
|
||||
width: 40,
|
||||
height: 5,
|
||||
backgroundColor: MainColor.white_gray,
|
||||
backgroundColor: MainColor.white,
|
||||
borderRadius: 5,
|
||||
alignSelf: "center",
|
||||
marginVertical: 10,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
// components/Select.tsx
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Modal,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
@@ -23,7 +21,9 @@ type SelectProps = {
|
||||
data: SelectItem[];
|
||||
value?: string | number | null;
|
||||
required?: boolean; // <-- new prop
|
||||
disabled?: boolean; // <-- tambahkan prop disabled
|
||||
onChange: (value: string | number) => void;
|
||||
borderRadius?: number;
|
||||
};
|
||||
|
||||
const SelectCustom: React.FC<SelectProps> = ({
|
||||
@@ -32,7 +32,9 @@ const SelectCustom: React.FC<SelectProps> = ({
|
||||
data,
|
||||
value,
|
||||
required = false, // <-- default false
|
||||
disabled = false, // <-- default false
|
||||
onChange,
|
||||
borderRadius = 8,
|
||||
}) => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
|
||||
@@ -41,35 +43,50 @@ const SelectCustom: React.FC<SelectProps> = ({
|
||||
const hasError = required && value === null; // <-- check if empty and required
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={GStyles.inputContainerArea}>
|
||||
{label && (
|
||||
<Text style={styles.label}>
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
{required && <Text style={styles.requiredIndicator}> *</Text>}
|
||||
{required && <Text style={GStyles.inputRequired}> *</Text>}
|
||||
</Text>
|
||||
)}
|
||||
<Pressable
|
||||
style={[styles.input, hasError ? styles.inputError : null]} // <-- add error style
|
||||
onPress={() => setModalVisible(true)}
|
||||
style={[
|
||||
{ borderRadius },
|
||||
hasError ? GStyles.inputErrorBorder : null,
|
||||
GStyles.inputContainerInput,
|
||||
disabled && GStyles.disabledBox,
|
||||
]} // <-- add error style
|
||||
onPress={() => !disabled && setModalVisible(true)}
|
||||
>
|
||||
<Text style={selectedItem ? styles.text : styles.placeholder}>
|
||||
<Text
|
||||
style={
|
||||
selectedItem
|
||||
? disabled
|
||||
? GStyles.inputTextDisabled
|
||||
: GStyles.inputText
|
||||
: disabled
|
||||
? GStyles.inputPlaceholderDisabled
|
||||
: GStyles.inputPlaceholder
|
||||
}
|
||||
>
|
||||
{selectedItem?.label || placeholder}
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
<Modal visible={modalVisible} transparent animationType="fade">
|
||||
<TouchableOpacity
|
||||
style={styles.modalOverlay}
|
||||
style={GStyles.selectModalOverlay}
|
||||
activeOpacity={1}
|
||||
onPressOut={() => setModalVisible(false)}
|
||||
>
|
||||
<View style={styles.modalContent}>
|
||||
<View style={GStyles.selectModalContent}>
|
||||
<FlatList
|
||||
data={data}
|
||||
keyExtractor={(item) => String(item.value)}
|
||||
renderItem={({ item }) => (
|
||||
<TouchableOpacity
|
||||
style={styles.option}
|
||||
style={GStyles.selectOption}
|
||||
onPress={() => {
|
||||
onChange(item.value);
|
||||
setModalVisible(false);
|
||||
@@ -85,68 +102,10 @@ const SelectCustom: React.FC<SelectProps> = ({
|
||||
|
||||
{/* Optional Error Message */}
|
||||
{hasError && (
|
||||
<Text style={styles.errorMessage}>Harap pilih salah satu</Text>
|
||||
<Text style={GStyles.inputErrorMessage}>Harap pilih salah satu</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectCustom;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
label: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
marginBottom: 4,
|
||||
color: MainColor.white_gray,
|
||||
fontWeight: "500",
|
||||
},
|
||||
requiredIndicator: {
|
||||
color: "red",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
input: {
|
||||
borderWidth: 1,
|
||||
borderColor: MainColor.white_gray,
|
||||
padding: 12,
|
||||
borderRadius: 8,
|
||||
minHeight: 48,
|
||||
justifyContent: "center",
|
||||
backgroundColor: MainColor.white,
|
||||
},
|
||||
inputError: {
|
||||
borderColor: "red",
|
||||
},
|
||||
text: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
},
|
||||
placeholder: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
color: MainColor.placeholder,
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: "rgba(0,0,0,0.3)",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
modalContent: {
|
||||
width: "80%",
|
||||
maxHeight: 300,
|
||||
backgroundColor: "white",
|
||||
borderRadius: 8,
|
||||
overflow: "hidden",
|
||||
},
|
||||
option: {
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#eee",
|
||||
},
|
||||
errorMessage: {
|
||||
marginTop: 4,
|
||||
fontSize: 12,
|
||||
color: "red",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ const StackCustom: React.FC<StackProps> = ({
|
||||
children,
|
||||
align = "stretch",
|
||||
justify = "flex-start",
|
||||
gap = "xs",
|
||||
gap = "md",
|
||||
direction = "column",
|
||||
style,
|
||||
}) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
TEXT_SIZE_SMALL,
|
||||
} from "@/constants/constans-value";
|
||||
import React from "react";
|
||||
import { Text as RNText, StyleProp, StyleSheet, TextStyle } from "react-native";
|
||||
import { Text as RNText, StyleProp, StyleSheet, TextStyle, TouchableOpacity } from "react-native";
|
||||
|
||||
// Tambahkan type TextAlignProps agar lebih type-safe
|
||||
type TextAlign = "left" | "center" | "right";
|
||||
@@ -19,6 +19,7 @@ interface TextCustomProps {
|
||||
color?: "default" | "yellow" | "red";
|
||||
align?: TextAlign; // Prop untuk alignment
|
||||
truncate?: boolean | number;
|
||||
onPress?: () => void;
|
||||
}
|
||||
|
||||
const TextCustom: React.FC<TextCustomProps> = ({
|
||||
@@ -30,6 +31,7 @@ const TextCustom: React.FC<TextCustomProps> = ({
|
||||
color = "default",
|
||||
align = "left", // Default alignment
|
||||
truncate = false,
|
||||
onPress,
|
||||
}) => {
|
||||
const getStyle = () => {
|
||||
let selectedStyles = [];
|
||||
@@ -61,15 +63,29 @@ const TextCustom: React.FC<TextCustomProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<RNText
|
||||
numberOfLines={
|
||||
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
|
||||
}
|
||||
ellipsizeMode="tail"
|
||||
style={getStyle()}
|
||||
>
|
||||
{children}
|
||||
</RNText>
|
||||
onPress ? (
|
||||
<TouchableOpacity onPress={onPress}>
|
||||
<RNText
|
||||
numberOfLines={
|
||||
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
|
||||
}
|
||||
ellipsizeMode="tail"
|
||||
style={getStyle()}
|
||||
>
|
||||
{children}
|
||||
</RNText>
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<RNText
|
||||
numberOfLines={
|
||||
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
|
||||
}
|
||||
ellipsizeMode="tail"
|
||||
style={getStyle()}
|
||||
>
|
||||
{children}
|
||||
</RNText>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
TextInput as RNTextInput,
|
||||
StyleProp,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle,
|
||||
TextInput as RNTextInput,
|
||||
StyleProp,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle,
|
||||
} from "react-native";
|
||||
|
||||
import { textInputStyles } from "../TextInput/textInputStyles";
|
||||
|
||||
type IconType = React.ReactNode | string;
|
||||
|
||||
type BaseProps = {
|
||||
@@ -71,31 +70,31 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
const renderIcon = (icon: IconType) => {
|
||||
if (!icon) return null;
|
||||
return typeof icon === "string" ? (
|
||||
<Text style={textInputStyles.iconText}>{icon}</Text>
|
||||
<Text style={GStyles.inputIconText}>{icon}</Text>
|
||||
) : (
|
||||
icon
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={textInputStyles.container}>
|
||||
<View style={GStyles.inputContainerArea}>
|
||||
{label && (
|
||||
<Text style={textInputStyles.label}>
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
{required && <Text style={textInputStyles.required}> *</Text>}
|
||||
{required && <Text style={GStyles.inputRequired}> *</Text>}
|
||||
</Text>
|
||||
)}
|
||||
<View
|
||||
style={[
|
||||
textInputStyles.inputContainer,
|
||||
disabled && textInputStyles.disabled,
|
||||
hasError ? textInputStyles.errorBorder : {},
|
||||
GStyles.inputContainerInput,
|
||||
disabled && GStyles.disabledBox,
|
||||
hasError ? GStyles.inputErrorBorder : {},
|
||||
{ borderRadius },
|
||||
style,
|
||||
]}
|
||||
>
|
||||
{iconLeft && (
|
||||
<View style={textInputStyles.icon}>{renderIcon(iconLeft)}</View>
|
||||
<View style={GStyles.inputIcon}>{renderIcon(iconLeft)}</View>
|
||||
)}
|
||||
|
||||
<RNTextInput
|
||||
@@ -103,8 +102,8 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
multiline
|
||||
numberOfLines={numberOfLines}
|
||||
style={[
|
||||
textInputStyles.input,
|
||||
textInputStyles.textArea,
|
||||
GStyles.inputText,
|
||||
GStyles.textAreaInput,
|
||||
{ color: fontColor },
|
||||
]}
|
||||
editable={!disabled}
|
||||
@@ -114,7 +113,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
/>
|
||||
|
||||
{iconRight && (
|
||||
<View style={textInputStyles.icon}>{renderIcon(iconRight)}</View>
|
||||
<View style={GStyles.inputIcon}>{renderIcon(iconRight)}</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -128,11 +127,11 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
|
||||
}}
|
||||
>
|
||||
{hasError ? (
|
||||
<Text style={textInputStyles.errorMessage}>{error}</Text>
|
||||
<Text style={GStyles.inputErrorMessage}>{error}</Text>
|
||||
) : null}
|
||||
|
||||
{showCount && maxLength ? (
|
||||
<Text style={textInputStyles.inputLength}>
|
||||
<Text style={GStyles.inputMaxLength}>
|
||||
{(value as string)?.length || 0}/{maxLength}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GStyles } from "@/styles/global-styles";
|
||||
import Ionicons from "@expo/vector-icons/Ionicons";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
@@ -8,7 +9,6 @@ import {
|
||||
View,
|
||||
ViewStyle,
|
||||
} from "react-native";
|
||||
import { textInputStyles } from "./textInputStyles";
|
||||
|
||||
type IconType = React.ReactNode | string;
|
||||
|
||||
@@ -26,7 +26,7 @@ type Props = {
|
||||
maxLength?: number;
|
||||
} & Omit<React.ComponentProps<typeof RNTextInput>, "style">;
|
||||
|
||||
export const TextInputCustom = ({
|
||||
const TextInputCustom = ({
|
||||
iconLeft,
|
||||
iconRight,
|
||||
label,
|
||||
@@ -49,7 +49,7 @@ export const TextInputCustom = ({
|
||||
const renderIcon = (icon: IconType) => {
|
||||
if (!icon) return null;
|
||||
return typeof icon === "string" ? (
|
||||
<Text style={textInputStyles.iconText}>{icon}</Text>
|
||||
<Text style={GStyles.inputIconText}>{icon}</Text>
|
||||
) : (
|
||||
icon
|
||||
);
|
||||
@@ -73,27 +73,31 @@ export const TextInputCustom = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={textInputStyles.container}>
|
||||
<View style={GStyles.inputContainerArea}>
|
||||
{label && (
|
||||
<Text style={textInputStyles.label}>
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
{required && <Text style={textInputStyles.required}> *</Text>}
|
||||
{required && <Text style={GStyles.inputRequired}> *</Text>}
|
||||
</Text>
|
||||
)}
|
||||
<View
|
||||
style={[
|
||||
textInputStyles.inputContainer,
|
||||
disabled && textInputStyles.disabled,
|
||||
{ borderRadius },
|
||||
externalError || internalError ? textInputStyles.errorBorder : null,
|
||||
style,
|
||||
{ borderRadius },
|
||||
externalError || internalError ? GStyles.inputErrorBorder : null,
|
||||
GStyles.inputContainerInput,
|
||||
disabled && GStyles.disabledBox,
|
||||
]}
|
||||
>
|
||||
{iconLeft && (
|
||||
<View style={textInputStyles.icon}>{renderIcon(iconLeft)}</View>
|
||||
)}
|
||||
{/* {iconLeft && (
|
||||
<View style={GStyles.inputIcon}>{renderIcon(iconLeft)}</View>
|
||||
)} */}
|
||||
<RNTextInput
|
||||
style={[textInputStyles.input, { color: fontColor }]}
|
||||
style={[
|
||||
GStyles.inputText,
|
||||
{ color: fontColor },
|
||||
disabled && GStyles.inputPlaceholderDisabled, // <-- placeholder saat disabled
|
||||
]}
|
||||
editable={!disabled}
|
||||
secureTextEntry={secureTextEntry && !isPasswordVisible}
|
||||
keyboardType={keyboardType}
|
||||
@@ -104,7 +108,7 @@ export const TextInputCustom = ({
|
||||
{secureTextEntry && (
|
||||
<TouchableOpacity
|
||||
onPress={() => setIsPasswordVisible((prev) => !prev)}
|
||||
style={textInputStyles.icon}
|
||||
style={GStyles.inputIcon}
|
||||
>
|
||||
<Ionicons
|
||||
name={isPasswordVisible ? "eye-off" : "eye"}
|
||||
@@ -114,15 +118,17 @@ export const TextInputCustom = ({
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{iconRight && (
|
||||
<View style={textInputStyles.icon}>{renderIcon(iconRight)}</View>
|
||||
<View style={GStyles.inputIcon}>{renderIcon(iconRight)}</View>
|
||||
)}
|
||||
</View>
|
||||
{/* Prioritaskan error eksternal */}
|
||||
{externalError || internalError ? (
|
||||
<Text style={textInputStyles.errorMessage}>
|
||||
<Text style={GStyles.inputErrorMessage}>
|
||||
{externalError || internalError}
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextInputCustom;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { TextInputCustom } from "./TextInputCustom";
|
||||
|
||||
export { TextInputCustom };
|
||||
@@ -1,85 +0,0 @@
|
||||
// components/text-input.styles.ts
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { TEXT_SIZE_LARGE, TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
export const textInputStyles = StyleSheet.create({
|
||||
// Container utama input (View luar)
|
||||
container: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
|
||||
// Label di atas input
|
||||
label: {
|
||||
fontSize: 14,
|
||||
marginBottom: 6,
|
||||
fontWeight: "500",
|
||||
color: MainColor.white_gray,
|
||||
},
|
||||
|
||||
// Tanda bintang merah untuk required
|
||||
required: {
|
||||
color: "red",
|
||||
},
|
||||
|
||||
// Pesan error di bawah input
|
||||
errorMessage: {
|
||||
marginTop: 4,
|
||||
fontSize: 12,
|
||||
color: MainColor.red,
|
||||
},
|
||||
|
||||
// Input Length
|
||||
inputLength: {
|
||||
fontSize: 12,
|
||||
color: MainColor.white_gray,
|
||||
},
|
||||
|
||||
// Wrapper input (View pembungkus TextInput)
|
||||
inputContainer: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
borderWidth: 1,
|
||||
borderColor: MainColor.white_gray,
|
||||
backgroundColor: MainColor.white,
|
||||
paddingHorizontal: 12,
|
||||
height: 50,
|
||||
},
|
||||
|
||||
// Style saat disabled
|
||||
disabled: {
|
||||
backgroundColor: "#f9f9f9",
|
||||
borderColor: "#e0e0e0",
|
||||
},
|
||||
|
||||
// Input utama (TextInput)
|
||||
input: {
|
||||
flex: 1,
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
paddingVertical: 0,
|
||||
},
|
||||
|
||||
// Ikon di kiri/kanan
|
||||
icon: {
|
||||
marginHorizontal: 4,
|
||||
justifyContent: "center",
|
||||
},
|
||||
|
||||
// Teks ikon jika berupa string
|
||||
iconText: {
|
||||
fontSize: TEXT_SIZE_LARGE,
|
||||
color: "#000",
|
||||
},
|
||||
|
||||
// Border merah jika ada error
|
||||
errorBorder: {
|
||||
borderColor: "red",
|
||||
},
|
||||
|
||||
// Untuk TextArea tambahan
|
||||
textArea: {
|
||||
textAlignVertical: "top",
|
||||
padding: 12,
|
||||
height: undefined, // biar multiline bebas tinggi
|
||||
},
|
||||
});
|
||||
@@ -4,7 +4,6 @@ import AlertCustom from "./Alert/AlertCustom";
|
||||
import LeftButtonCustom from "./Button/BackButton";
|
||||
import ButtonCenteredOnly from "./Button/ButtonCenteredOnly";
|
||||
import ButtonCustom from "./Button/ButtonCustom";
|
||||
import ButtonUpload from "./Button/ButtonUpload";
|
||||
// Drawer
|
||||
import DrawerCustom from "./Drawer/DrawerCustom";
|
||||
import MenuDrawerDynamicGrid from "./Drawer/MenuDrawerDynamicGird";
|
||||
@@ -14,32 +13,42 @@ import ViewWrapper from "./_ShareComponent/ViewWrapper";
|
||||
// Text
|
||||
import TextCustom from "./Text/TextCustom";
|
||||
// TextInput
|
||||
import { TextInputCustom } from "./TextInput/TextInputCustom";
|
||||
import TextInputCustom from "./TextInput/TextInputCustom";
|
||||
// TextArea
|
||||
import TextAreaCustom from "./TextArea/TextAreaCustom";
|
||||
// Grid
|
||||
import Grid from "./Grid/GridCustom";
|
||||
// Box
|
||||
import BaseBox from "./Box/BaseBox";
|
||||
// Avatar
|
||||
import AvatarCustom from "./Image/AvatarCustom";
|
||||
import BoxButtonOnFooter from "./Box/BoxButtonOnFooter";
|
||||
import InformationBox from "./Box/InformationBox";
|
||||
|
||||
// Stack
|
||||
import StackCustom from "./Stack/StackCustom";
|
||||
// Select
|
||||
import SelectCustom from "./Select/SelectCustom";
|
||||
// Image
|
||||
import AvatarCustom from "./Image/AvatarCustom";
|
||||
import LandscapeFrameUploaded from "./Image/LandscapeFrameUploaded";
|
||||
|
||||
export {
|
||||
AlertCustom,
|
||||
// Avatar
|
||||
// Image
|
||||
AvatarCustom,
|
||||
LandscapeFrameUploaded,
|
||||
// Button
|
||||
ButtonCustom,
|
||||
LeftButtonCustom as BackButton,
|
||||
ButtonCenteredOnly,
|
||||
// Box
|
||||
BaseBox, ButtonCenteredOnly, ButtonCustom, ButtonUpload,
|
||||
BaseBox,
|
||||
BoxButtonOnFooter,
|
||||
InformationBox,
|
||||
// Drawer
|
||||
DrawerCustom,
|
||||
// Grid
|
||||
Grid, MenuDrawerDynamicGrid,
|
||||
Grid,
|
||||
MenuDrawerDynamicGrid,
|
||||
// Select
|
||||
SelectCustom,
|
||||
// ShareComponent
|
||||
@@ -53,6 +62,5 @@ export {
|
||||
// TextInput
|
||||
TextInputCustom,
|
||||
// ViewWrapper
|
||||
ViewWrapper
|
||||
ViewWrapper,
|
||||
};
|
||||
|
||||
|
||||
@@ -3,24 +3,27 @@ export const MainColor = {
|
||||
darkblue: "#001D3D",
|
||||
soft_darkblue: "#0e3763",
|
||||
yellow: "#E1B525",
|
||||
white_gray: "#D4D0D0",
|
||||
red: "#FF4B4C",
|
||||
orange: "#FF7043",
|
||||
green: "#4CAF4F",
|
||||
white_gray: "#D4D0D0",
|
||||
text_input: "#EDEBEBFF",
|
||||
placeholder: "#999",
|
||||
disabled: "#606360",
|
||||
placeholder: "#888",
|
||||
white: "#ffffff",
|
||||
// disabled color
|
||||
disabled: "#777",
|
||||
};
|
||||
|
||||
export const AccentColor = {
|
||||
blackgray: "#333533FF",
|
||||
blackgray: "#aaa",
|
||||
darkblue: "#002E59",
|
||||
blue: "#00447D",
|
||||
softblue: "#007CBA",
|
||||
skyblue: "#00BFFF",
|
||||
yellow: "#F8A824",
|
||||
white: "#FEFFFE",
|
||||
// disable color
|
||||
disabledBorder: "#aaa",
|
||||
};
|
||||
|
||||
export const AdminColor = {
|
||||
|
||||
@@ -31,8 +31,8 @@ export default function LoginView() {
|
||||
console.log("login user id :", id);
|
||||
|
||||
// router.navigate("/verification");
|
||||
router.navigate(`/(application)/(user)/profile/${id}`);
|
||||
// router.navigate("/(application)/home");
|
||||
// router.navigate(`/(application)/(user)/profile/${id}`);
|
||||
router.navigate("/(application)/(user)/home");
|
||||
// router.navigate(`/(application)/profile/${id}/edit`);
|
||||
}
|
||||
|
||||
|
||||
33
screens/Portofolio/ListPage.tsx
Normal file
33
screens/Portofolio/ListPage.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
|
||||
export const drawerItemsPortofolio = ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
}): IMenuDrawerItem[] => [
|
||||
{
|
||||
icon: "create",
|
||||
label: "Edit portofolio",
|
||||
path: `/(application)/portofolio/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: "camera",
|
||||
label: "Edit logo ",
|
||||
path: `/(application)/portofolio/${id}/edit-logo`,
|
||||
},
|
||||
{
|
||||
icon: "image",
|
||||
label: "Edit social media ",
|
||||
path: `/(application)/portofolio/${id}/edit-social-media`,
|
||||
},
|
||||
{
|
||||
icon: "add-circle",
|
||||
label: "Edit Map",
|
||||
path: `/(application)/maps/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: "create-outline",
|
||||
label: "Custom Pin Map",
|
||||
path: `/(application)/maps/${id}/custom-pin`,
|
||||
},
|
||||
];
|
||||
28
screens/Portofolio/MenuDrawer.tsx
Normal file
28
screens/Portofolio/MenuDrawer.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import MenuDrawerDynamicGrid from "@/components/Drawer/MenuDrawerDynamicGird";
|
||||
import { router } from "expo-router";
|
||||
|
||||
export default function Portofolio_MenuDrawerSection({
|
||||
drawerItems,
|
||||
setIsDrawerOpen,
|
||||
}: {
|
||||
drawerItems: IMenuDrawerItem[];
|
||||
setIsDrawerOpen: (value: boolean) => void;
|
||||
}) {
|
||||
const handlePress = (item: IMenuDrawerItem) => {
|
||||
console.log("PATH >> ", item.path);
|
||||
router.push(item.path as any);
|
||||
setIsDrawerOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Menu Items */}
|
||||
<MenuDrawerDynamicGrid
|
||||
data={drawerItems}
|
||||
columns={4} // Ubah ke 2 jika ingin 2 kolom per baris
|
||||
onPressItem={handlePress}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
35
screens/Profile/ListPage.tsx
Normal file
35
screens/Profile/ListPage.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
|
||||
export const drawerItemsProfile = ({ id }: { id: string }): IMenuDrawerItem[] => [
|
||||
{
|
||||
icon: "create",
|
||||
label: "Edit profile",
|
||||
path: `/(application)/profile/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: "camera",
|
||||
label: "Ubah foto profile",
|
||||
path: `/(application)/profile/${id}/update-photo`,
|
||||
},
|
||||
{
|
||||
icon: "image",
|
||||
label: "Ubah latar belakang",
|
||||
path: `/(application)/profile/${id}/update-background`,
|
||||
},
|
||||
{
|
||||
icon: "add-circle",
|
||||
label: "Tambah portofolio",
|
||||
path: `/(application)/portofolio/${id}/create`,
|
||||
},
|
||||
// {
|
||||
// icon: "settings",
|
||||
// label: "Dashboard Admin",
|
||||
// path: `/(application)/profile/dashboard-admin`,
|
||||
// },
|
||||
{ icon: "log-out", label: "Keluar", color: "red", path: "" },
|
||||
{
|
||||
icon: "create-outline",
|
||||
label: "Create profile",
|
||||
path: `/(application)/profile/${id}/create`,
|
||||
},
|
||||
];
|
||||
@@ -115,9 +115,15 @@ export default function ProfilSection() {
|
||||
</BaseBox>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<TextCustom
|
||||
bold
|
||||
align="right"
|
||||
onPress={() => router.push(`/portofolio/${id}/list`)}
|
||||
>
|
||||
Lihat semua
|
||||
</TextCustom>
|
||||
</BaseBox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import {
|
||||
TEXT_SIZE_LARGE,
|
||||
TEXT_SIZE_MEDIUM,
|
||||
TEXT_SIZE_SMALL,
|
||||
} from "@/constants/constans-value";
|
||||
import { Dimensions, StyleSheet } from "react-native";
|
||||
import { AccentColor, MainColor } from "../constants/color-palet";
|
||||
|
||||
const { width } = Dimensions.get("window");
|
||||
|
||||
export const GStyles = StyleSheet.create({
|
||||
// =============== Main Styles =============== //
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingInline: 20,
|
||||
@@ -20,8 +25,25 @@ export const GStyles = StyleSheet.create({
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
},
|
||||
// Style saat disabled
|
||||
disabledBox: {
|
||||
backgroundColor: MainColor.disabled,
|
||||
borderColor: AccentColor.disabledBorder,
|
||||
},
|
||||
|
||||
// AUTHENTICATION
|
||||
inputDisabled: {
|
||||
backgroundColor: "#f0f0f0",
|
||||
borderColor: "#ddd",
|
||||
},
|
||||
inputTextDisabled: {
|
||||
color: "#777",
|
||||
},
|
||||
inputPlaceholderDisabled: {
|
||||
color: "#444",
|
||||
},
|
||||
// =============== Main Styles =============== //
|
||||
|
||||
// =============== AUTHENTICATION =============== //
|
||||
authContainer: {
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
@@ -40,30 +62,35 @@ export const GStyles = StyleSheet.create({
|
||||
color: MainColor.yellow,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
// =============== AUTHENTICATION =============== //
|
||||
|
||||
// TEXT & LABEL
|
||||
// =============== TEXT & LABEL =============== //
|
||||
textLabel: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
color: MainColor.white_gray,
|
||||
fontWeight: "normal",
|
||||
},
|
||||
// =============== TEXT & LABEL =============== //
|
||||
|
||||
// Stack Header Style
|
||||
// =============== STACK HEADER =============== //
|
||||
headerStyle: {
|
||||
backgroundColor: AccentColor.darkblue,
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: MainColor.yellow,
|
||||
fontWeight: "bold",
|
||||
fontSize: TEXT_SIZE_LARGE,
|
||||
},
|
||||
// =============== STACK HEADER =============== //
|
||||
|
||||
// HOME
|
||||
// =============== HOME =============== //
|
||||
homeContainer: {
|
||||
flex: 1,
|
||||
paddingInline: 25,
|
||||
paddingBlock: 10,
|
||||
backgroundColor: MainColor.darkblue,
|
||||
},
|
||||
// =============== HOME =============== //
|
||||
|
||||
// =============== TAB =============== //
|
||||
tabBar: {
|
||||
@@ -141,14 +168,6 @@ export const GStyles = StyleSheet.create({
|
||||
backgroundColor: MainColor.darkblue,
|
||||
borderTopColor: AccentColor.blue,
|
||||
borderTopWidth: 1,
|
||||
// shadowColor: AccentColor.blue,
|
||||
// shadowOffset: {
|
||||
// width: 0,
|
||||
// height: -1,
|
||||
// },
|
||||
// shadowOpacity: 0.9,
|
||||
// shadowRadius: 5,
|
||||
// elevation: 5,
|
||||
},
|
||||
bottomBarContainer: {
|
||||
paddingHorizontal: 15,
|
||||
@@ -157,8 +176,113 @@ export const GStyles = StyleSheet.create({
|
||||
// =============== BOTTOM BAR =============== //
|
||||
|
||||
// =============== BUTTON =============== //
|
||||
|
||||
buttonCentered50Percent: {
|
||||
width: "50%",
|
||||
alignSelf: "center",
|
||||
},
|
||||
// =============== BUTTON =============== //
|
||||
|
||||
// =============== TEXT INPUT , TEXT AREA , SELECT =============== //
|
||||
// Container utama input (View luar)
|
||||
inputContainerArea: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
|
||||
// Label di atas input
|
||||
inputLabel: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
marginBottom: 4,
|
||||
fontWeight: "500",
|
||||
color: MainColor.white_gray,
|
||||
},
|
||||
|
||||
// Tanda bintang merah untuk required
|
||||
inputRequired: {
|
||||
color: "red",
|
||||
},
|
||||
|
||||
// Pesan error di bawah input
|
||||
inputErrorMessage: {
|
||||
marginTop: 4,
|
||||
fontSize: TEXT_SIZE_SMALL,
|
||||
color: MainColor.red,
|
||||
},
|
||||
|
||||
// Input Length
|
||||
inputMaxLength: {
|
||||
fontSize: TEXT_SIZE_SMALL,
|
||||
color: MainColor.white_gray,
|
||||
},
|
||||
|
||||
// Wrapper input (View pembungkus TextInput)
|
||||
inputContainerInput: {
|
||||
borderWidth: 1,
|
||||
borderColor: MainColor.white_gray,
|
||||
backgroundColor: MainColor.white,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 10,
|
||||
height: 50,
|
||||
},
|
||||
|
||||
// Input utama (TextInput)
|
||||
inputText: {
|
||||
flex: 1,
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
paddingVertical: 0,
|
||||
},
|
||||
|
||||
// Ikon di kiri/kanan
|
||||
inputIcon: {
|
||||
marginHorizontal: 4,
|
||||
justifyContent: "center",
|
||||
},
|
||||
|
||||
// Teks ikon jika berupa string
|
||||
inputIconText: {
|
||||
fontSize: TEXT_SIZE_LARGE,
|
||||
color: "#000",
|
||||
},
|
||||
|
||||
// Border merah jika ada error
|
||||
inputErrorBorder: {
|
||||
borderColor: "red",
|
||||
borderWidth: 1,
|
||||
},
|
||||
|
||||
// Placeholder input
|
||||
inputPlaceholder: {
|
||||
fontSize: TEXT_SIZE_MEDIUM,
|
||||
color: MainColor.placeholder,
|
||||
},
|
||||
|
||||
// TextArea untuk tambahan
|
||||
textAreaInput: {
|
||||
textAlignVertical: "top",
|
||||
padding: 5,
|
||||
height: undefined, // biar multiline bebas tinggi
|
||||
},
|
||||
|
||||
// Select
|
||||
selectModalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: "rgba(0,0,0,0.3)",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
selectModalContent: {
|
||||
width: "80%",
|
||||
maxHeight: 300,
|
||||
backgroundColor: "white",
|
||||
borderRadius: 8,
|
||||
overflow: "hidden",
|
||||
},
|
||||
selectOption: {
|
||||
padding: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: MainColor.white_gray,
|
||||
},
|
||||
|
||||
// =============== TEXT INPUT , TEXT AREA , SELECT =============== //
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user