Deskripsi:

- new comp : Radio
- fix comp : Text area > placeholder diatas
- fix page : report forum sudah pakai radio

# No Issue
This commit is contained in:
2025-07-15 12:01:28 +08:00
parent a0dad5618a
commit 3376336c55
8 changed files with 192 additions and 28 deletions

View File

@@ -11,7 +11,7 @@ import {
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection"; import Forum_BoxDetailSection from "@/screens/Forum/DiscussionBoxSection";
import { listDataDummyCommentarForum } from "@/screens/Forum/list-data-dummy"; import { listDummyDiscussionForum } from "@/screens/Forum/list-data-dummy";
import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda"; import Forum_MenuDrawerBerandaSection from "@/screens/Forum/MenuDrawerSection.tsx/MenuBeranda";
import { useLocalSearchParams } from "expo-router"; import { useLocalSearchParams } from "expo-router";
import { useState } from "react"; import { useState } from "react";
@@ -47,12 +47,14 @@ export default function Forumku() {
</ButtonCustom> </ButtonCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
{listDataDummyCommentarForum.map((e, i) => ( {listDummyDiscussionForum.map((e, i) => (
<Forum_BoxDetailSection <Forum_BoxDetailSection
key={i} key={i}
data={e} data={e}
setOpenDrawer={setOpenDrawer} setOpenDrawer={setOpenDrawer}
setStatus={setStatus} setStatus={setStatus}
isTruncate={true}
href={`/forum/${id}`}
/> />
))} ))}
</StackCustom> </StackCustom>

View File

@@ -1,10 +1,10 @@
import { import {
AlertCustom, AlertCustom,
ButtonCustom, ButtonCustom,
DrawerCustom, DrawerCustom,
Spacing, Spacing,
TextAreaCustom, TextAreaCustom,
ViewWrapper ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection"; import Forum_CommentarBoxSection from "@/screens/Forum/CommentarBoxSection";
@@ -26,6 +26,7 @@ export default function ForumDetail() {
// Comentar // Comentar
const [openDrawerCommentar, setOpenDrawerCommentar] = useState(false); const [openDrawerCommentar, setOpenDrawerCommentar] = useState(false);
const [alertDeleteCommentar, setAlertDeleteCommentar] = useState(false);
const dataDummy = { const dataDummy = {
name: "Bagas", name: "Bagas",
@@ -76,7 +77,6 @@ export default function ForumDetail() {
key={i} key={i}
data={e} data={e}
setOpenDrawer={setOpenDrawerCommentar} setOpenDrawer={setOpenDrawerCommentar}
/> />
))} ))}
</ViewWrapper> </ViewWrapper>
@@ -148,23 +148,23 @@ export default function ForumDetail() {
setIsDrawerOpen={() => { setIsDrawerOpen={() => {
setOpenDrawerCommentar(false); setOpenDrawerCommentar(false);
}} }}
setShowDeleteAlert={setDeleteAlert} setShowDeleteAlert={setAlertDeleteCommentar}
/> />
</DrawerCustom> </DrawerCustom>
{/* Alert Delete Commentar */} {/* Alert Delete Commentar */}
<AlertCustom <AlertCustom
isVisible={deleteAlert} isVisible={alertDeleteCommentar}
title="Hapus Komentar" title="Hapus Komentar"
message="Apakah Anda yakin ingin menghapus komentar ini?" message="Apakah Anda yakin ingin menghapus komentar ini?"
onLeftPress={() => { onLeftPress={() => {
setOpenDrawerCommentar(false); setOpenDrawerCommentar(false);
setDeleteAlert(false); setAlertDeleteCommentar(false);
console.log("Batal"); console.log("Batal");
}} }}
onRightPress={() => { onRightPress={() => {
setOpenDrawerCommentar(false); setOpenDrawerCommentar(false);
setDeleteAlert(false); setAlertDeleteCommentar(false);
console.log("Hapus commentar"); console.log("Hapus commentar");
}} }}
textLeft="Batal" textLeft="Batal"

View File

@@ -1,5 +1,6 @@
import { import {
ButtonCustom, ButtonCustom,
Spacing,
StackCustom, StackCustom,
ViewWrapper ViewWrapper
} from "@/components"; } from "@/components";
@@ -33,6 +34,7 @@ export default function ForumReportCommentar() {
> >
Lainnya Lainnya
</ButtonCustom> </ButtonCustom>
<Spacing/>
</StackCustom> </StackCustom>
</ViewWrapper> </ViewWrapper>
</> </>

View File

@@ -1,4 +1,4 @@
import { ViewWrapper, StackCustom, ButtonCustom } from "@/components"; import { ViewWrapper, StackCustom, ButtonCustom, Spacing } from "@/components";
import { MainColor, AccentColor } from "@/constants/color-palet"; import { MainColor, AccentColor } from "@/constants/color-palet";
import Forum_ReportListSection from "@/screens/Forum/ReportListSection"; import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
import { router } from "expo-router"; import { router } from "expo-router";
@@ -29,6 +29,7 @@ export default function ForumReportPosting() {
> >
Lainnya Lainnya
</ButtonCustom> </ButtonCustom>
<Spacing />
</StackCustom> </StackCustom>
</ViewWrapper> </ViewWrapper>
</> </>

View File

@@ -0,0 +1,132 @@
// components/Radio.tsx
import { GStyles } from '@/styles/global-styles';
import React, { createContext, useCallback, useContext } from 'react';
import {
StyleSheet,
Text,
TextStyle,
TouchableOpacity,
View,
ViewStyle
} from 'react-native';
// ========================
// Types
// ========================
type RadioContextType = {
value: string;
onChange: (value: string) => void;
};
const RadioContext = createContext<RadioContextType | undefined>(undefined);
interface RadioGroupProps {
value: string;
onChange: (value: string) => void;
children: React.ReactNode;
style?: ViewStyle;
}
interface RadioProps {
label: string;
value: string | number;
disabled?: boolean;
style?: ViewStyle;
labelStyle?: TextStyle;
}
// ========================
// Components
// ========================
export const RadioGroup: React.FC<RadioGroupProps> = ({ value, onChange, children, style }) => {
const contextValue = {
value,
onChange,
};
return <RadioContext.Provider value={contextValue}>{children}</RadioContext.Provider>;
};
export const RadioCustom: React.FC<RadioProps> = ({ label, value, disabled = false, style, labelStyle }) => {
const context = useContext(RadioContext);
if (!context) {
throw new Error('Radio must be used inside a RadioGroup');
}
const { value: selectedValue, onChange } = context;
const handlePress = useCallback(() => {
if (!disabled && selectedValue !== value) {
onChange(value as any);
}
}, [disabled, selectedValue, value, onChange]);
const isSelected = selectedValue === value;
return (
<TouchableOpacity
style={[styles.radioContainer, style]}
onPress={handlePress}
disabled={disabled}
>
{/* Circle */}
<View
style={[styles.outerCircle, isSelected && styles.outerCircleChecked]}
>
<View
style={[styles.innerCircle, isSelected && styles.innerCircleChecked]}
/>
</View>
{/* Label */}
<Text
style={[
GStyles.textLabelBold,
labelStyle,
disabled && GStyles.inputTextDisabled,
]}
>
{label}
</Text>
</TouchableOpacity>
);
};
// ========================
// Styles
// ========================
const styles = StyleSheet.create({
radioContainer: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 8,
},
outerCircle: {
height: 24,
width: 24,
borderRadius: 12,
borderWidth: 2,
borderColor: '#3B82F6',
justifyContent: 'center',
alignItems: 'center',
marginRight: 10,
},
outerCircleChecked: {
backgroundColor: '#3B82F6',
},
innerCircle: {
height: 12,
width: 12,
borderRadius: 6,
backgroundColor: 'transparent',
},
innerCircleChecked: {
backgroundColor: 'white',
borderColor: 'white',
borderRadius: 6,
},
});

View File

@@ -105,7 +105,7 @@ const TextAreaCustom: React.FC<TextAreaCustomProps> = ({
multiline multiline
numberOfLines={numberOfLines} numberOfLines={numberOfLines}
style={[ style={[
GStyles.inputText, // GStyles.inputText,
GStyles.textAreaInput, GStyles.textAreaInput,
{ color: fontColor }, { color: fontColor },
]} ]}

View File

@@ -1,18 +1,39 @@
import { BaseBox, StackCustom, TextCustom } from "@/components"; import { BaseBox, ButtonCustom, StackCustom, TextCustom } from "@/components";
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
import { MainColor } from "@/constants/color-palet";
import { listDummyReportForum } from "@/lib/dummy-data/forum/report-list"; import { listDummyReportForum } from "@/lib/dummy-data/forum/report-list";
import { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native"; import { View } from "react-native";
export default function Forum_ReportListSection() { export default function Forum_ReportListSection() {
const [value, setValue] = useState<any | number>("");
return ( return (
<> <>
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
{listDummyReportForum.map((e, i) => ( <RadioGroup value={value} onChange={setValue}>
<View key={i}> {listDummyReportForum.map((e, i) => (
<TextCustom>{e.title}</TextCustom> <View key={i}>
<TextCustom>{e.desc}</TextCustom> <RadioCustom
</View> label={e.title}
))} // value={i}
value={e.title}
/>
<TextCustom>{e.desc}</TextCustom>
</View>
))}
</RadioGroup>
{/* <ButtonCustom
backgroundColor={MainColor.red}
textColor={MainColor.white}
onPress={() => {
console.log("Report", value);
}}
>
Report
</ButtonCustom> */}
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
</> </>

View File

@@ -44,17 +44,16 @@ export const GStyles = StyleSheet.create({
}, },
floatingContainer: { floatingContainer: {
position: "absolute", position: "absolute",
bottom: 80, bottom: 100,
right: 20, right: 20,
zIndex: 8, zIndex: 8,
}, },
// Style saat disabled // =============== Disabled Styles =============== //
disabledBox: { disabledBox: {
backgroundColor: MainColor.disabled, backgroundColor: MainColor.disabled,
borderColor: AccentColor.disabledBorder, borderColor: AccentColor.disabledBorder,
}, },
inputDisabled: { inputDisabled: {
backgroundColor: "#f0f0f0", backgroundColor: "#f0f0f0",
borderColor: "#ddd", borderColor: "#ddd",
@@ -65,7 +64,7 @@ export const GStyles = StyleSheet.create({
inputPlaceholderDisabled: { inputPlaceholderDisabled: {
color: "#444", color: "#444",
}, },
// =============== Main Styles =============== // // =============== Disabled Styles =============== //
// =============== AUTHENTICATION =============== // // =============== AUTHENTICATION =============== //
authContainer: { authContainer: {
@@ -94,6 +93,11 @@ export const GStyles = StyleSheet.create({
color: MainColor.white_gray, color: MainColor.white_gray,
fontWeight: "normal", fontWeight: "normal",
}, },
textLabelBold: {
fontSize: TEXT_SIZE_MEDIUM,
color: MainColor.white_gray,
fontWeight: "bold",
},
// =============== TEXT & LABEL =============== // // =============== TEXT & LABEL =============== //
// =============== STACK HEADER =============== // // =============== STACK HEADER =============== //
@@ -284,8 +288,10 @@ export const GStyles = StyleSheet.create({
// TextArea untuk tambahan // TextArea untuk tambahan
textAreaInput: { textAreaInput: {
textAlignVertical: "top", textAlignVertical: "top",
padding: 5, paddingTop: 10,
height: undefined, // biar multiline bebas tinggi // height: undefined, // biar multiline bebas tinggi
height: 100,
width: "100%",
}, },
// Select // Select