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";
import { MainColor } from "@/constants/color-palet";
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 { useLocalSearchParams } from "expo-router";
import { useState } from "react";
@@ -47,12 +47,14 @@ export default function Forumku() {
</ButtonCustom>
</Grid.Col>
</Grid>
{listDataDummyCommentarForum.map((e, i) => (
{listDummyDiscussionForum.map((e, i) => (
<Forum_BoxDetailSection
key={i}
data={e}
setOpenDrawer={setOpenDrawer}
setStatus={setStatus}
isTruncate={true}
href={`/forum/${id}`}
/>
))}
</StackCustom>

View File

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

View File

@@ -1,5 +1,6 @@
import {
ButtonCustom,
Spacing,
StackCustom,
ViewWrapper
} from "@/components";
@@ -33,6 +34,7 @@ export default function ForumReportCommentar() {
>
Lainnya
</ButtonCustom>
<Spacing/>
</StackCustom>
</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 Forum_ReportListSection from "@/screens/Forum/ReportListSection";
import { router } from "expo-router";
@@ -29,6 +29,7 @@ export default function ForumReportPosting() {
>
Lainnya
</ButtonCustom>
<Spacing />
</StackCustom>
</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
numberOfLines={numberOfLines}
style={[
GStyles.inputText,
// GStyles.inputText,
GStyles.textAreaInput,
{ 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 { router } from "expo-router";
import { useState } from "react";
import { View } from "react-native";
export default function Forum_ReportListSection() {
const [value, setValue] = useState<any | number>("");
return (
<>
<BaseBox>
<StackCustom>
{listDummyReportForum.map((e, i) => (
<View key={i}>
<TextCustom>{e.title}</TextCustom>
<TextCustom>{e.desc}</TextCustom>
</View>
))}
<RadioGroup value={value} onChange={setValue}>
{listDummyReportForum.map((e, i) => (
<View key={i}>
<RadioCustom
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>
</BaseBox>
</>

View File

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