deskripsi:
- tampilan edit profile
- resourcing stack
- fix text input & buttom
This commit is contained in:
2025-07-03 16:35:39 +08:00
parent 101c9053d8
commit 7b58e3315f
8 changed files with 99 additions and 17 deletions

View File

@@ -1,17 +1,64 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
import { TextInputCustom, ViewWrapper } from "@/components"; import {
import { StackCustom } from "@/components/Stack"; ButtonCustom,
StackCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import { useLocalSearchParams } from "expo-router"; import { useLocalSearchParams } from "expo-router";
import { useState } from "react";
import { Text } from "react-native";
export default function ProfileEdit() { export default function ProfileEdit() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [nama, setNama] = useState("Bagas Banuna");
const [email, setEmail] = useState("bagasbanuna@gmail.com");
const [alamat, setAlamat] = useState("Bandar Lampung");
return ( return (
<ViewWrapper> <ViewWrapper
<StackCustom> bottomBarComponent={
<TextInputCustom label="Nama" value="Nama" required /> <ButtonCustom
<TextInputCustom label="Email" value="Email" required /> radius={30}
<TextInputCustom label="Alamat" value="Alamat" required /> disabled={!nama || !email || !alamat}
onPress={() => {
console.log("data >>", nama, email, alamat);
}}
>
Simpan
</ButtonCustom>
}
>
<StackCustom gap={"xs"}>
<TextInputCustom
label="Nama"
placeholder="Nama"
value={nama}
onChangeText={(text) => {
setNama(text);
}}
required
/>
<TextInputCustom
label="Email"
placeholder="Email"
value={email}
onChangeText={(text) => {
setEmail(text);
}}
required
/>
<TextInputCustom
label="Alamat"
placeholder="Alamat"
value={alamat}
onChangeText={(text) => {
setAlamat(text);
}}
required
/>
</StackCustom> </StackCustom>
</ViewWrapper> </ViewWrapper>
); );

View File

@@ -3,11 +3,13 @@
import React from "react"; import React from "react";
import { Text, TouchableOpacity } from "react-native"; import { Text, TouchableOpacity } from "react-native";
import buttonStyles from "./buttonCustomStyles"; import buttonStyles from "./buttonCustomStyles";
import { RADIUS_BUTTON } from "@/constants/constans-value";
// Definisi props dengan TypeScript // Definisi props dengan TypeScript
interface ButtonProps { interface ButtonProps {
onPress: () => void; children?: React.ReactNode;
onPress?: () => void;
title?: string; title?: string;
backgroundColor?: string; backgroundColor?: string;
textColor?: string; textColor?: string;
@@ -28,6 +30,7 @@ interface ButtonProps {
* @example iconLeft={<Icon name="arrow-right" size={20} color={MainColor.black}/> * @example iconLeft={<Icon name="arrow-right" size={20} color={MainColor.black}/>
*/ */
const ButtonCustom: React.FC<ButtonProps> = ({ const ButtonCustom: React.FC<ButtonProps> = ({
children,
onPress, onPress,
title = "Button", title = "Button",
backgroundColor = "#007AFF", backgroundColor = "#007AFF",
@@ -39,7 +42,7 @@ const ButtonCustom: React.FC<ButtonProps> = ({
const styles = buttonStyles({ const styles = buttonStyles({
backgroundColor, backgroundColor,
textColor, textColor,
borderRadius: radius, borderRadius: RADIUS_BUTTON || radius,
}); });
return ( return (
@@ -51,7 +54,7 @@ const ButtonCustom: React.FC<ButtonProps> = ({
> >
{/* Render icon jika tersedia */} {/* Render icon jika tersedia */}
{iconLeft && iconLeft} {iconLeft && iconLeft}
<Text style={styles.buttonText}>{title}</Text> <Text style={styles.buttonText}>{children}</Text>
</TouchableOpacity> </TouchableOpacity>
); );
}; };

View File

@@ -1,3 +0,0 @@
import StackCustom from "./StackCustom";
export { StackCustom };

View File

@@ -11,7 +11,7 @@ import { Text as RNText, StyleProp, StyleSheet, TextStyle } from "react-native";
type TextAlign = "left" | "center" | "right"; type TextAlign = "left" | "center" | "right";
interface TextCustomProps { interface TextCustomProps {
children: string; children: string | React.ReactNode;
style?: StyleProp<TextStyle>; style?: StyleProp<TextStyle>;
bold?: boolean; bold?: boolean;
semiBold?: boolean; semiBold?: boolean;

View File

@@ -7,12 +7,14 @@ interface ViewWrapperProps {
children: React.ReactNode; children: React.ReactNode;
withBackground?: boolean; withBackground?: boolean;
tabBarComponent?: React.ReactNode; tabBarComponent?: React.ReactNode;
bottomBarComponent?: React.ReactNode;
} }
const ViewWrapper = ({ const ViewWrapper = ({
children, children,
withBackground = false, withBackground = false,
tabBarComponent, tabBarComponent,
bottomBarComponent,
}: ViewWrapperProps) => { }: ViewWrapperProps) => {
const assetBackground = require("../../assets/images/main-background.png"); const assetBackground = require("../../assets/images/main-background.png");
@@ -42,10 +44,17 @@ const ViewWrapper = ({
<View style={GStyles.container}>{children}</View> <View style={GStyles.container}>{children}</View>
)} )}
</ScrollView> </ScrollView>
{tabBarComponent} {tabBarComponent ? tabBarComponent : null}
{bottomBarComponent ? (
<View style={GStyles.bottomBar}>
<View style={GStyles.bottomBarContainer}>
{bottomBarComponent}
</View>
</View>
) : null}
</SafeAreaView> </SafeAreaView>
</> </>
// <SafeAreaProvider> // <SafeAreaProvider>
// <SafeAreaView // <SafeAreaView
// edges={[ // edges={[

View File

@@ -19,6 +19,8 @@ import Grid from "./Grid/GridCustom";
import BaseBox from "./Box/BaseBox"; import BaseBox from "./Box/BaseBox";
// Avatar // Avatar
import AvatarCustom from "./Avatar/AvatarCustom" import AvatarCustom from "./Avatar/AvatarCustom"
// Stack
import StackCustom from "./Stack/StackCustom";
export { export {
AlertCustom, AlertCustom,
@@ -41,4 +43,6 @@ export {
BaseBox, BaseBox,
// Avatar // Avatar
AvatarCustom, AvatarCustom,
// Stack
StackCustom,
}; };

View File

@@ -5,6 +5,7 @@ export {
ICON_SIZE_SMALL, ICON_SIZE_SMALL,
ICON_SIZE_MEDIUM, ICON_SIZE_MEDIUM,
DRAWER_HEIGHT, DRAWER_HEIGHT,
RADIUS_BUTTON,
}; };
const TEXT_SIZE_SMALL = 12; const TEXT_SIZE_SMALL = 12;
@@ -13,3 +14,4 @@ const TEXT_SIZE_LARGE = 16;
const ICON_SIZE_SMALL = 20; const ICON_SIZE_SMALL = 20;
const ICON_SIZE_MEDIUM = 24; const ICON_SIZE_MEDIUM = 24;
const DRAWER_HEIGHT = 500; // tinggi drawer5 const DRAWER_HEIGHT = 500; // tinggi drawer5
const RADIUS_BUTTON = 50

View File

@@ -135,4 +135,24 @@ export const GStyles = StyleSheet.create({
backgroundColor: "#007AFF", backgroundColor: "#007AFF",
}, },
// =============== TAB =============== // // =============== TAB =============== //
// =============== BOTTOM BAR =============== //
bottomBar: {
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,
paddingVertical: 10,
},
// =============== BOTTOM BAR =============== //
}); });