deskripsi:
- perubahan pada component: ButtonCustom, TextArea, TextInput
- fix style global
- tambhan color pada palet
This commit is contained in:
2025-07-09 15:03:41 +08:00
parent 2901d19db0
commit b7e774a556
14 changed files with 178 additions and 133 deletions

View File

@@ -1,6 +1,6 @@
{ {
"expo": { "expo": {
"name": "hipmi-mobile", "name": "HIPMI BADUNG",
"slug": "hipmi-mobile", "slug": "hipmi-mobile",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { import {
BoxButtonOnFooter, BoxButtonOnFooter,
ButtonCenteredOnly, ButtonCenteredOnly,
@@ -18,7 +17,7 @@ import { MainColor } from "@/constants/color-palet";
import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis"; import dummyMasterBidangBisnis from "@/lib/dummy-data/master-bidang-bisnis";
import dummyMasterSubBidangBisnis from "@/lib/dummy-data/master-sub-bidang-bisnis"; import dummyMasterSubBidangBisnis from "@/lib/dummy-data/master-sub-bidang-bisnis";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import { useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import { useState } from "react"; import { useState } from "react";
import { Text, TouchableOpacity, View } from "react-native"; import { Text, TouchableOpacity, View } from "react-native";
import PhoneInput, { ICountry } from "react-native-international-phone-number"; import PhoneInput, { ICountry } from "react-native-international-phone-number";
@@ -60,11 +59,13 @@ export default function PortofolioCreate() {
<StackCustom> <StackCustom>
<InformationBox text="Lengkapi data bisnis anda." /> <InformationBox text="Lengkapi data bisnis anda." />
<TextInputCustom <TextInputCustom
// disabled
required required
label="Nama Bisnis" label="Nama Bisnis"
placeholder="Masukkan nama bisnis" placeholder="Masukkan nama bisnis"
/> />
<SelectCustom <SelectCustom
// disabled
label="Bidang Usaha" label="Bidang Usaha"
required required
data={dummyMasterBidangBisnis.map((item) => ({ data={dummyMasterBidangBisnis.map((item) => ({
@@ -80,6 +81,7 @@ export default function PortofolioCreate() {
<Grid> <Grid>
<Grid.Col span={10}> <Grid.Col span={10}>
<SelectCustom <SelectCustom
// disabled
label="Sub Bidang Usaha" label="Sub Bidang Usaha"
required required
data={dummyMasterSubBidangBisnis.map((item) => ({ data={dummyMasterSubBidangBisnis.map((item) => ({
@@ -145,12 +147,22 @@ export default function PortofolioCreate() {
maxLength={100} maxLength={100}
/> />
<Spacing /> <Spacing />
{/* Logo */}
<InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." /> <InformationBox text="Upload logo bisnis anda untuk di tampilaka pada portofolio." />
<LandscapeFrameUploaded /> <LandscapeFrameUploaded />
<ButtonCenteredOnly icon="upload" onPress={() => console.log("upload")}> <ButtonCenteredOnly
icon="upload"
onPress={() => {
console.log("Upload logo >>", id);
router.navigate(`/(application)/take-picture/${id}`);
}}
>
Upload Upload
</ButtonCenteredOnly> </ButtonCenteredOnly>
<Spacing height={40} /> <Spacing height={40} />
{/* Social Media */}
<InformationBox text="Isi hanya pada sosial media yang anda miliki." /> <InformationBox text="Isi hanya pada sosial media yang anda miliki." />
<TextInputCustom <TextInputCustom
label="Tiktok" label="Tiktok"

View File

@@ -1,5 +1,6 @@
import { import {
AvatarCustom, AvatarCustom,
ButtonCenteredOnly,
ButtonCustom, ButtonCustom,
SelectCustom, SelectCustom,
Spacing, Spacing,
@@ -9,7 +10,6 @@ import {
} from "@/components"; } from "@/components";
import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter"; import BoxButtonOnFooter from "@/components/Box/BoxButtonOnFooter";
import InformationBox from "@/components/Box/InformationBox"; import InformationBox from "@/components/Box/InformationBox";
import ButtonUpload from "@/components/Button/ButtonUpload";
import LandscapeFrameUploaded from "@/components/Image/LandscapeFrameUploaded"; import LandscapeFrameUploaded from "@/components/Image/LandscapeFrameUploaded";
import { router, useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import { useState } from "react"; import { useState } from "react";
@@ -47,9 +47,12 @@ export default function CreateProfile() {
<View style={{ alignItems: "center" }}> <View style={{ alignItems: "center" }}>
<AvatarCustom size="xl" /> <AvatarCustom size="xl" />
<Spacing /> <Spacing />
<ButtonUpload <ButtonCenteredOnly
icon="upload"
onPress={() => router.navigate(`/take-picture/${id}`)} onPress={() => router.navigate(`/take-picture/${id}`)}
/> >
Upload
</ButtonCenteredOnly>
</View> </View>
<Spacing /> <Spacing />
@@ -58,9 +61,12 @@ export default function CreateProfile() {
<InformationBox text="Upload foto latar belakang anda." /> <InformationBox text="Upload foto latar belakang anda." />
<LandscapeFrameUploaded /> <LandscapeFrameUploaded />
<Spacing /> <Spacing />
<ButtonUpload <ButtonCenteredOnly
icon="upload"
onPress={() => router.navigate(`/take-picture/${id}`)} onPress={() => router.navigate(`/take-picture/${id}`)}
/> >
Upload
</ButtonCenteredOnly>
</View> </View>
<Spacing /> <Spacing />

View File

@@ -1,15 +1,18 @@
import { BaseBox, ButtonCustom } from "@/components"; import {
BaseBox,
BoxButtonOnFooter,
ButtonCenteredOnly,
ButtonCustom,
} from "@/components";
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper"; import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
import ButtonUpload from "@/components/Button/ButtonUpload";
import DUMMY_IMAGE from "@/constants/dummy-image-value"; import DUMMY_IMAGE from "@/constants/dummy-image-value";
import { router, useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import { Image } from "react-native"; import { Image } from "react-native";
export default function UpdateBackgroundProfile() { export default function UpdateBackgroundProfile() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
return ( const buttonFooter = (
<ViewWrapper <BoxButtonOnFooter>
bottomBarComponent={
<ButtonCustom <ButtonCustom
onPress={() => { onPress={() => {
console.log("Simpan foto background >>", id); console.log("Simpan foto background >>", id);
@@ -18,8 +21,11 @@ export default function UpdateBackgroundProfile() {
> >
Simpan Simpan
</ButtonCustom> </ButtonCustom>
} </BoxButtonOnFooter>
> );
return (
<ViewWrapper footerComponent={buttonFooter}>
<BaseBox <BaseBox
style={{ alignItems: "center", justifyContent: "center", height: 250 }} style={{ alignItems: "center", justifyContent: "center", height: 250 }}
> >
@@ -30,12 +36,12 @@ export default function UpdateBackgroundProfile() {
/> />
</BaseBox> </BaseBox>
<ButtonUpload <ButtonCenteredOnly
title="Update" icon="upload"
onPress={() => onPress={() => router.navigate(`/(application)/take-picture/${id}`)}
router.navigate(`/(application)/take-picture/${id}`) >
} Update
/> </ButtonCenteredOnly>
</ViewWrapper> </ViewWrapper>
); );
} }

View File

@@ -1,15 +1,18 @@
import { BaseBox, ButtonCustom } from "@/components"; import {
BaseBox,
BoxButtonOnFooter,
ButtonCenteredOnly,
ButtonCustom,
} from "@/components";
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper"; import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
import ButtonUpload from "@/components/Button/ButtonUpload";
import DUMMY_IMAGE from "@/constants/dummy-image-value"; import DUMMY_IMAGE from "@/constants/dummy-image-value";
import { router, useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import { Image } from "react-native"; import { Image } from "react-native";
export default function UpdatePhotoProfile() { export default function UpdatePhotoProfile() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
return ( const buttonFooter = (
<ViewWrapper <BoxButtonOnFooter>
bottomBarComponent={
<ButtonCustom <ButtonCustom
onPress={() => { onPress={() => {
console.log("Simpan foto profile >>", id); console.log("Simpan foto profile >>", id);
@@ -18,8 +21,10 @@ export default function UpdatePhotoProfile() {
> >
Simpan Simpan
</ButtonCustom> </ButtonCustom>
} </BoxButtonOnFooter>
> );
return (
<ViewWrapper footerComponent={buttonFooter}>
<BaseBox <BaseBox
style={{ alignItems: "center", justifyContent: "center", height: 250 }} style={{ alignItems: "center", justifyContent: "center", height: 250 }}
> >
@@ -30,13 +35,18 @@ export default function UpdatePhotoProfile() {
/> />
</BaseBox> </BaseBox>
<ButtonUpload <ButtonCenteredOnly
title="Update" icon="upload"
onPress={() => { onPress={() => {
console.log("Update photo >>", id); console.log("Update photo >>", id);
router.navigate(`/(application)/take-picture/${id}`); router.navigate(`/(application)/take-picture/${id}`);
}} }}
/> >
Update
</ButtonCenteredOnly>
{/* <Spacing />
<ButtonCustom>Test</ButtonCustom> */}
</ViewWrapper> </ViewWrapper>
); );
} }

View File

@@ -2,13 +2,12 @@
import React from "react"; import React from "react";
import { StyleProp, Text, TouchableOpacity, ViewStyle } from "react-native"; import { StyleProp, Text, TouchableOpacity, ViewStyle } from "react-native";
import buttonStyles from "./buttonCustomStyles";
import { radiusMap } from "@/constants/radius-value"; import { radiusMap } from "@/constants/radius-value";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { stylesButton } from "./buttonCustomStyles";
// Import radiusMap // Import radiusMap
// Definisi type untuk radius // Definisi type untuk radius
type RadiusType = keyof typeof radiusMap | number; type RadiusType = keyof typeof radiusMap | number;
@@ -30,30 +29,29 @@ const ButtonCustom: React.FC<ButtonProps> = ({
title = "Button", title = "Button",
backgroundColor = MainColor.yellow, backgroundColor = MainColor.yellow,
textColor = MainColor.black, textColor = MainColor.black,
radius = "full", // default md radius = 50, // default md
disabled = false, disabled = false,
iconLeft, iconLeft,
style, style,
}) => { }) => {
const borderRadius =
typeof radius === "number" ? radius : radiusMap[radius ?? "md"]; // fallback ke 'md'
const styles = buttonStyles({
backgroundColor,
textColor,
borderRadius,
});
return ( return (
<TouchableOpacity <TouchableOpacity
style={[styles.button, disabled && styles.disabled, style]} style={[
stylesButton.button,
disabled && stylesButton.disabled,
style,
{ borderRadius: radius },
{ backgroundColor },
]}
onPress={onPress} onPress={onPress}
disabled={disabled} disabled={disabled}
activeOpacity={0.8} activeOpacity={0.8}
> >
{/* Render icon jika tersedia */} {/* Render icon jika tersedia */}
{iconLeft && iconLeft} {iconLeft && iconLeft}
<Text style={styles.buttonText}>{children || title}</Text> <Text style={[stylesButton.buttonText, { color: textColor }]}>
{children || title}
</Text>
</TouchableOpacity> </TouchableOpacity>
); );
}; };

View File

@@ -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>
);
}

View File

@@ -4,24 +4,18 @@ import { MainColor } from "@/constants/color-palet";
import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value"; import { TEXT_SIZE_MEDIUM } from "@/constants/constans-value";
import { StyleSheet } from "react-native"; import { StyleSheet } from "react-native";
export default function buttonStyles({ export const stylesButton = StyleSheet.create({
backgroundColor = "#007AFF",
textColor = "#FFFFFF",
borderRadius = 8,
}) {
return StyleSheet.create({
button: { button: {
backgroundColor, backgroundColor: MainColor.yellow,
paddingVertical: 12, paddingVertical: 12,
paddingHorizontal: 20, paddingHorizontal: 20,
borderRadius,
flexDirection: "row", // 👈 Tambahkan baris ini flexDirection: "row", // 👈 Tambahkan baris ini
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
gap: 8, gap: 8,
}, },
buttonText: { buttonText: {
color: textColor, color: MainColor.black,
fontSize: TEXT_SIZE_MEDIUM, fontSize: TEXT_SIZE_MEDIUM,
fontWeight: "600", fontWeight: "600",
}, },
@@ -29,4 +23,3 @@ export default function buttonStyles({
backgroundColor: MainColor.disabled, backgroundColor: MainColor.disabled,
}, },
}); });
}

View File

@@ -7,7 +7,7 @@ import {
Pressable, Pressable,
Text, Text,
TouchableOpacity, TouchableOpacity,
View View,
} from "react-native"; } from "react-native";
type SelectItem = { type SelectItem = {
@@ -21,6 +21,7 @@ type SelectProps = {
data: SelectItem[]; data: SelectItem[];
value?: string | number | null; value?: string | number | null;
required?: boolean; // <-- new prop required?: boolean; // <-- new prop
disabled?: boolean; // <-- tambahkan prop disabled
onChange: (value: string | number) => void; onChange: (value: string | number) => void;
borderRadius?: number; borderRadius?: number;
}; };
@@ -31,6 +32,7 @@ const SelectCustom: React.FC<SelectProps> = ({
data, data,
value, value,
required = false, // <-- default false required = false, // <-- default false
disabled = false, // <-- default false
onChange, onChange,
borderRadius = 8, borderRadius = 8,
}) => { }) => {
@@ -51,13 +53,22 @@ const SelectCustom: React.FC<SelectProps> = ({
<Pressable <Pressable
style={[ style={[
{ borderRadius }, { borderRadius },
GStyles.inputContainerInput,
hasError ? GStyles.inputErrorBorder : null, hasError ? GStyles.inputErrorBorder : null,
GStyles.inputContainerInput,
disabled && GStyles.disabledBox,
]} // <-- add error style ]} // <-- add error style
onPress={() => setModalVisible(true)} onPress={() => !disabled && setModalVisible(true)}
> >
<Text <Text
style={selectedItem ? GStyles.inputText : GStyles.inputPlaceholder} style={
selectedItem
? disabled
? GStyles.inputTextDisabled
: GStyles.inputText
: disabled
? GStyles.inputPlaceholderDisabled
: GStyles.inputPlaceholder
}
> >
{selectedItem?.label || placeholder} {selectedItem?.label || placeholder}
</Text> </Text>

View File

@@ -87,7 +87,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
<View <View
style={[ style={[
GStyles.inputContainerInput, GStyles.inputContainerInput,
disabled && GStyles.inputDisabled, disabled && GStyles.disabledBox,
hasError ? GStyles.inputErrorBorder : {}, hasError ? GStyles.inputErrorBorder : {},
{ borderRadius }, { borderRadius },
style, style,

View File

@@ -10,7 +10,6 @@ import {
ViewStyle, ViewStyle,
} from "react-native"; } from "react-native";
type IconType = React.ReactNode | string; type IconType = React.ReactNode | string;
type Props = { type Props = {
@@ -83,18 +82,27 @@ const TextInputCustom = ({
)} )}
<View <View
style={[ style={[
GStyles.inputContainerInput, style,
disabled && GStyles.inputDisabled,
{ borderRadius }, { borderRadius },
externalError || internalError ? GStyles.inputErrorBorder : null, externalError || internalError ? GStyles.inputErrorBorder : null,
style, GStyles.inputContainerInput,
disabled && GStyles.disabledBox,
]} ]}
> >
{iconLeft && ( {iconLeft && (
<View style={GStyles.inputIcon}>{renderIcon(iconLeft)}</View> <View style={GStyles.inputIcon}>{renderIcon(iconLeft)}</View>
)} )}
<RNTextInput <RNTextInput
style={[GStyles.inputText, { color: fontColor }]} style={[
GStyles.inputText,
{ color: fontColor },
disabled
? GStyles.inputTextDisabled // <-- custom style untuk text saat disabled
: GStyles.inputText,
disabled
? GStyles.inputPlaceholderDisabled // <-- placeholder saat disabled
: GStyles.inputPlaceholder,
]}
editable={!disabled} editable={!disabled}
secureTextEntry={secureTextEntry && !isPasswordVisible} secureTextEntry={secureTextEntry && !isPasswordVisible}
keyboardType={keyboardType} keyboardType={keyboardType}

View File

@@ -4,7 +4,6 @@ import AlertCustom from "./Alert/AlertCustom";
import LeftButtonCustom from "./Button/BackButton"; import LeftButtonCustom from "./Button/BackButton";
import ButtonCenteredOnly from "./Button/ButtonCenteredOnly"; import ButtonCenteredOnly from "./Button/ButtonCenteredOnly";
import ButtonCustom from "./Button/ButtonCustom"; import ButtonCustom from "./Button/ButtonCustom";
import ButtonUpload from "./Button/ButtonUpload";
// Drawer // Drawer
import DrawerCustom from "./Drawer/DrawerCustom"; import DrawerCustom from "./Drawer/DrawerCustom";
import MenuDrawerDynamicGrid from "./Drawer/MenuDrawerDynamicGird"; import MenuDrawerDynamicGrid from "./Drawer/MenuDrawerDynamicGird";
@@ -38,12 +37,11 @@ export {
AvatarCustom, AvatarCustom,
LandscapeFrameUploaded, LandscapeFrameUploaded,
// Button // Button
ButtonCustom,
LeftButtonCustom as BackButton, LeftButtonCustom as BackButton,
ButtonCenteredOnly,
// Box // Box
BaseBox, BaseBox,
ButtonCenteredOnly,
ButtonCustom,
ButtonUpload,
BoxButtonOnFooter, BoxButtonOnFooter,
InformationBox, InformationBox,
// Drawer // Drawer

View File

@@ -3,24 +3,27 @@ export const MainColor = {
darkblue: "#001D3D", darkblue: "#001D3D",
soft_darkblue: "#0e3763", soft_darkblue: "#0e3763",
yellow: "#E1B525", yellow: "#E1B525",
white_gray: "#D4D0D0",
red: "#FF4B4C", red: "#FF4B4C",
orange: "#FF7043", orange: "#FF7043",
green: "#4CAF4F", green: "#4CAF4F",
white_gray: "#D4D0D0",
text_input: "#EDEBEBFF", text_input: "#EDEBEBFF",
placeholder: "#999", placeholder: "#888",
disabled: "#606360",
white: "#ffffff", white: "#ffffff",
// disabled color
disabled: "#777",
}; };
export const AccentColor = { export const AccentColor = {
blackgray: "#333533FF", blackgray: "#aaa",
darkblue: "#002E59", darkblue: "#002E59",
blue: "#00447D", blue: "#00447D",
softblue: "#007CBA", softblue: "#007CBA",
skyblue: "#00BFFF", skyblue: "#00BFFF",
yellow: "#F8A824", yellow: "#F8A824",
white: "#FEFFFE", white: "#FEFFFE",
// disable color
disabledBorder: "#aaa",
}; };
export const AdminColor = { export const AdminColor = {

View File

@@ -1,10 +1,15 @@
import { TEXT_SIZE_LARGE, TEXT_SIZE_MEDIUM, TEXT_SIZE_SMALL } 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 { Dimensions, StyleSheet } from "react-native";
import { AccentColor, MainColor } from "../constants/color-palet"; import { AccentColor, MainColor } from "../constants/color-palet";
const { width } = Dimensions.get("window"); const { width } = Dimensions.get("window");
export const GStyles = StyleSheet.create({ export const GStyles = StyleSheet.create({
// =============== Main Styles =============== //
container: { container: {
flex: 1, flex: 1,
paddingInline: 20, paddingInline: 20,
@@ -20,8 +25,25 @@ export const GStyles = StyleSheet.create({
height: "100%", height: "100%",
width: "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: { authContainer: {
flex: 1, flex: 1,
justifyContent: "center", justifyContent: "center",
@@ -40,15 +62,17 @@ export const GStyles = StyleSheet.create({
color: MainColor.yellow, color: MainColor.yellow,
fontWeight: "bold", fontWeight: "bold",
}, },
// =============== AUTHENTICATION =============== //
// TEXT & LABEL // =============== TEXT & LABEL =============== //
textLabel: { textLabel: {
fontSize: TEXT_SIZE_MEDIUM, fontSize: TEXT_SIZE_MEDIUM,
color: MainColor.white_gray, color: MainColor.white_gray,
fontWeight: "normal", fontWeight: "normal",
}, },
// =============== TEXT & LABEL =============== //
// Stack Header Style // =============== STACK HEADER =============== //
headerStyle: { headerStyle: {
backgroundColor: AccentColor.darkblue, backgroundColor: AccentColor.darkblue,
}, },
@@ -56,14 +80,16 @@ export const GStyles = StyleSheet.create({
color: MainColor.yellow, color: MainColor.yellow,
fontWeight: "bold", fontWeight: "bold",
}, },
// =============== STACK HEADER =============== //
// HOME // =============== HOME =============== //
homeContainer: { homeContainer: {
flex: 1, flex: 1,
paddingInline: 25, paddingInline: 25,
paddingBlock: 10, paddingBlock: 10,
backgroundColor: MainColor.darkblue, backgroundColor: MainColor.darkblue,
}, },
// =============== HOME =============== //
// =============== TAB =============== // // =============== TAB =============== //
tabBar: { tabBar: {
@@ -149,6 +175,7 @@ export const GStyles = StyleSheet.create({
// =============== BOTTOM BAR =============== // // =============== BOTTOM BAR =============== //
// =============== BUTTON =============== // // =============== BUTTON =============== //
buttonCentered50Percent: { buttonCentered50Percent: {
width: "50%", width: "50%",
alignSelf: "center", alignSelf: "center",
@@ -198,12 +225,6 @@ export const GStyles = StyleSheet.create({
height: 50, height: 50,
}, },
// Style saat disabled
inputDisabled: {
backgroundColor: "#f9f9f9",
borderColor: "#e0e0e0",
},
// Input utama (TextInput) // Input utama (TextInput)
inputText: { inputText: {
flex: 1, flex: 1,