feature & fix
deskripsi: - new component : Scroll - fix : notifikasi, use search, portofolio item drawer - new constats : padding value - fix component : Text custom : tambah warna gray di props Text Input: tambah props container Style # No Issue
This commit is contained in:
@@ -1,9 +1,118 @@
|
||||
import { TextCustom, ViewWrapper } from "@/components";
|
||||
import {
|
||||
BaseBox,
|
||||
Grid,
|
||||
ScrollableCustom,
|
||||
StackCustom,
|
||||
TextCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import { MainColor } from "@/constants/color-palet";
|
||||
import { useState } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
const categories = [
|
||||
{ id: 1, label: "Semua" },
|
||||
{ id: 2, label: "Event" },
|
||||
{ id: 3, label: "Job" },
|
||||
{ id: 4, label: "Voting" },
|
||||
{ id: 5, label: "Donasi" },
|
||||
{ id: 6, label: "Investasi" },
|
||||
{ id: 7, label: "Forum" },
|
||||
{ id: 8, label: "Collaboration" },
|
||||
];
|
||||
|
||||
const selectedCategory = (id: number) => {
|
||||
const category = categories.find((c) => c.id === id);
|
||||
return category?.label;
|
||||
};
|
||||
|
||||
const BoxNotification = ({
|
||||
index,
|
||||
activeCategory,
|
||||
}: {
|
||||
index: number;
|
||||
activeCategory: number | null;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<BaseBox
|
||||
onPress={() =>
|
||||
console.log(
|
||||
"Notification >",
|
||||
selectedCategory(activeCategory as number)
|
||||
)
|
||||
}
|
||||
>
|
||||
<StackCustom>
|
||||
<TextCustom bold>
|
||||
# {selectedCategory(activeCategory as number)}
|
||||
</TextCustom>
|
||||
|
||||
<View
|
||||
style={{
|
||||
borderBottomColor: MainColor.white_gray,
|
||||
borderBottomWidth: 1,
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextCustom truncate={2}>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint odio
|
||||
unde quidem voluptate quam culpa sequi molestias ipsa corrupti id,
|
||||
soluta, nostrum adipisci similique, et illo asperiores deleniti eum
|
||||
labore.
|
||||
</TextCustom>
|
||||
|
||||
<Grid>
|
||||
<Grid.Col span={6}>
|
||||
<TextCustom size="small" color="gray">
|
||||
{index + 1} Agustus 2025
|
||||
</TextCustom>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
||||
<TextCustom size="small" color="gray">
|
||||
Belum lihat
|
||||
</TextCustom>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</StackCustom>
|
||||
</BaseBox>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Notifications() {
|
||||
const [activeCategory, setActiveCategory] = useState<number | null>(1);
|
||||
|
||||
const handlePress = (item: any) => {
|
||||
setActiveCategory(item.id);
|
||||
// tambahkan logika lain seperti filter dsb.
|
||||
};
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<TextCustom>Notifications</TextCustom>
|
||||
<ViewWrapper
|
||||
headerComponent={
|
||||
<ScrollableCustom
|
||||
data={categories}
|
||||
onButtonPress={handlePress}
|
||||
activeId={activeCategory as any}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{Array.from({ length: 20 }).map((e, i) => (
|
||||
<View key={i}>
|
||||
<BoxNotification index={i} activeCategory={activeCategory} />
|
||||
</View>
|
||||
))}
|
||||
|
||||
{/* Konten utama di sini */}
|
||||
{/* <View style={{ flex: 1 }}>
|
||||
<Text style={{ color: "white" }}>
|
||||
{activeCategory
|
||||
? `Kategori Aktif: ${
|
||||
categories.find((c) => c.id === activeCategory)?.label
|
||||
}`
|
||||
: "Pilih kategori"}
|
||||
</Text>
|
||||
</View> */}
|
||||
</ViewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ export default function UserSearch() {
|
||||
}
|
||||
placeholder="Cari Pengguna"
|
||||
borderRadius={50}
|
||||
containerStyle={{ marginBottom: 0 }}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { StyleSheet } from "react-native";
|
||||
export const stylesButton = StyleSheet.create({
|
||||
button: {
|
||||
backgroundColor: MainColor.yellow,
|
||||
paddingVertical: 12,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 20,
|
||||
flexDirection: "row", // 👈 Tambahkan baris ini
|
||||
alignItems: "center",
|
||||
|
||||
60
components/Scroll/ScrollCustom.tsx
Normal file
60
components/Scroll/ScrollCustom.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||
import React from "react";
|
||||
import { ScrollView, StyleSheet } from "react-native";
|
||||
import ButtonCustom from "../Button/ButtonCustom";
|
||||
|
||||
interface ButtonData {
|
||||
id: string | number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface ScrollableCustomProps {
|
||||
data: ButtonData[];
|
||||
onButtonPress: (item: ButtonData) => void;
|
||||
activeId?: string | number;
|
||||
}
|
||||
|
||||
const ScrollableCustom = ({
|
||||
data,
|
||||
onButtonPress,
|
||||
activeId,
|
||||
}: ScrollableCustomProps) => {
|
||||
return (
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={styles.buttonContainer}
|
||||
style={styles.scrollView}
|
||||
>
|
||||
{data.map((item) => {
|
||||
const isActive = activeId === item.id;
|
||||
|
||||
return (
|
||||
<ButtonCustom
|
||||
key={item.id}
|
||||
backgroundColor={isActive ? MainColor.yellow : AccentColor.blue}
|
||||
textColor={isActive ? MainColor.black : MainColor.white}
|
||||
onPress={() => onButtonPress(item)}
|
||||
>
|
||||
{item.label}
|
||||
</ButtonCustom>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScrollableCustom;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scrollView: {
|
||||
// maxHeight: 50,
|
||||
},
|
||||
buttonContainer: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
// paddingHorizontal: 16,
|
||||
// paddingVertical: 10,
|
||||
gap: 12,
|
||||
},
|
||||
});
|
||||
@@ -22,7 +22,7 @@ interface TextCustomProps {
|
||||
bold?: boolean;
|
||||
semiBold?: boolean;
|
||||
size?: "default" | "large" | "small";
|
||||
color?: "default" | "yellow" | "red";
|
||||
color?: "default" | "yellow" | "red" | "gray";
|
||||
align?: TextAlign; // Prop untuk alignment
|
||||
truncate?: boolean | number;
|
||||
onPress?: () => void;
|
||||
@@ -56,6 +56,7 @@ const TextCustom: React.FC<TextCustomProps> = ({
|
||||
// Color
|
||||
if (color === "yellow") selectedStyles.push(styles.yellow);
|
||||
else if (color === "red") selectedStyles.push(styles.red);
|
||||
else if (color === "gray") selectedStyles.push(styles.gray);
|
||||
|
||||
// Alignment
|
||||
if (align) {
|
||||
@@ -122,4 +123,7 @@ export const styles = StyleSheet.create({
|
||||
red: {
|
||||
color: MainColor.red,
|
||||
},
|
||||
gray: {
|
||||
color: MainColor.placeholder,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -24,6 +24,7 @@ type Props = {
|
||||
borderRadius?: number;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
maxLength?: number;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
} & Omit<React.ComponentProps<typeof RNTextInput>, "style">;
|
||||
|
||||
const TextInputCustom = ({
|
||||
@@ -40,6 +41,7 @@ const TextInputCustom = ({
|
||||
keyboardType,
|
||||
onChangeText,
|
||||
maxLength,
|
||||
containerStyle,
|
||||
...rest
|
||||
}: Props) => {
|
||||
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
||||
@@ -73,7 +75,7 @@ const TextInputCustom = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={GStyles.inputContainerArea}>
|
||||
<View style={[GStyles.inputContainerArea, containerStyle]}>
|
||||
{label && (
|
||||
<Text style={GStyles.inputLabel}>
|
||||
{label}
|
||||
|
||||
@@ -37,6 +37,8 @@ import MapCustom from "./Map/MapCustom";
|
||||
import CenterCustom from "./Center/CenterCustom";
|
||||
// Clickable
|
||||
import ClickableCustom from "./Clickable/ClickableCustom";
|
||||
// Scroll
|
||||
import ScrollableCustom from "./Scroll/ScrollCustom";
|
||||
|
||||
export {
|
||||
AlertCustom,
|
||||
@@ -78,4 +80,6 @@ export {
|
||||
CenterCustom,
|
||||
// Clickable
|
||||
ClickableCustom,
|
||||
// Scroll
|
||||
ScrollableCustom,
|
||||
};
|
||||
|
||||
@@ -7,13 +7,31 @@ export {
|
||||
DRAWER_HEIGHT,
|
||||
RADIUS_BUTTON,
|
||||
ICON_SIZE_BUTTON,
|
||||
PADDING_EXTRA_SMALL,
|
||||
PADDING_SMALL,
|
||||
PADDING_MEDIUM,
|
||||
PADDING_LARGE,
|
||||
};
|
||||
|
||||
// Text Size
|
||||
const TEXT_SIZE_SMALL = 12;
|
||||
const TEXT_SIZE_MEDIUM = 14;
|
||||
const TEXT_SIZE_LARGE = 16;
|
||||
|
||||
// Icon Size
|
||||
const ICON_SIZE_BUTTON = 18
|
||||
const ICON_SIZE_SMALL = 20;
|
||||
const ICON_SIZE_MEDIUM = 24;
|
||||
|
||||
// Drawer Height
|
||||
const DRAWER_HEIGHT = 500; // tinggi drawer5
|
||||
|
||||
// Radius Button
|
||||
const RADIUS_BUTTON = 50
|
||||
const ICON_SIZE_BUTTON = 18
|
||||
|
||||
// Padding
|
||||
const PADDING_EXTRA_SMALL = 10
|
||||
const PADDING_SMALL = 12
|
||||
const PADDING_MEDIUM = 16
|
||||
const PADDING_LARGE = 20
|
||||
|
||||
|
||||
@@ -1,35 +1,61 @@
|
||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||
import { AccentColor } from "@/constants/color-palet";
|
||||
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Ionicons, FontAwesome5, FontAwesome, Fontisto } from "@expo/vector-icons";
|
||||
|
||||
export const drawerItemsPortofolio = ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
}): IMenuDrawerItem[] => [
|
||||
export const drawerItemsPortofolio = ({ id }: { id: string }): IMenuDrawerItem[] => [
|
||||
{
|
||||
icon: <Ionicons name="create" size={ICON_SIZE_MEDIUM} color={AccentColor.white} />,
|
||||
icon: (
|
||||
<Ionicons
|
||||
name="create"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Edit portofolio",
|
||||
path: `/(application)/portofolio/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: <Ionicons name="camera" size={ICON_SIZE_MEDIUM} color={AccentColor.white} />,
|
||||
icon: (
|
||||
<Ionicons
|
||||
name="camera"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Edit logo ",
|
||||
path: `/(application)/portofolio/${id}/edit-logo`,
|
||||
},
|
||||
{
|
||||
icon: <Ionicons name="image" size={ICON_SIZE_MEDIUM} color={AccentColor.white} />,
|
||||
icon: (
|
||||
<FontAwesome
|
||||
name="id-card-o"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Edit social media ",
|
||||
path: `/(application)/portofolio/${id}/edit-social-media`,
|
||||
},
|
||||
{
|
||||
icon: <Ionicons name="add-circle" size={ICON_SIZE_MEDIUM} color={AccentColor.white} />,
|
||||
icon: (
|
||||
<Fontisto
|
||||
name="map-marker-alt"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Edit Map",
|
||||
path: `/(application)/maps/${id}/edit`,
|
||||
},
|
||||
{
|
||||
icon: <Ionicons name="create-outline" size={ICON_SIZE_MEDIUM} color={AccentColor.white} />,
|
||||
icon: (
|
||||
<FontAwesome5
|
||||
name="map-pin"
|
||||
size={ICON_SIZE_MEDIUM}
|
||||
color={AccentColor.white}
|
||||
/>
|
||||
),
|
||||
label: "Custom Pin Map",
|
||||
path: `/(application)/maps/${id}/custom-pin`,
|
||||
},
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import {
|
||||
PADDING_EXTRA_SMALL,
|
||||
PADDING_LARGE,
|
||||
PADDING_MEDIUM,
|
||||
PADDING_SMALL,
|
||||
TEXT_SIZE_LARGE,
|
||||
TEXT_SIZE_MEDIUM,
|
||||
TEXT_SIZE_SMALL,
|
||||
@@ -12,28 +16,28 @@ export const GStyles = StyleSheet.create({
|
||||
// =============== Main Styles =============== //
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingInline: 20,
|
||||
paddingBlock: 10,
|
||||
paddingInline: PADDING_LARGE,
|
||||
paddingBlock: PADDING_EXTRA_SMALL,
|
||||
backgroundColor: MainColor.darkblue,
|
||||
},
|
||||
containerWithBackground: {
|
||||
flex: 1,
|
||||
paddingInline: 20,
|
||||
paddingBlock: 10,
|
||||
paddingInline: PADDING_LARGE,
|
||||
paddingBlock: PADDING_EXTRA_SMALL,
|
||||
},
|
||||
imageBackground: {
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
},
|
||||
stickyHeader: {
|
||||
position: "absolute",
|
||||
position: "relative",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 10,
|
||||
backgroundColor: MainColor.darkblue,
|
||||
paddingTop: 16,
|
||||
paddingInline: 16,
|
||||
backgroundColor: "transparent",
|
||||
paddingBlock: PADDING_SMALL,
|
||||
paddingInline: PADDING_MEDIUM,
|
||||
// padding: 16,
|
||||
// paddingTop: 8,
|
||||
// paddingBottom: 8,
|
||||
|
||||
Reference in New Issue
Block a user