Skip to content

Commit 02cf681

Browse files
committed
Add CheckCircleIcon and PlaceholderIcon components; update HomeScreen to use CustomCard
1 parent 9a75cea commit 02cf681

File tree

6 files changed

+416
-44
lines changed

6 files changed

+416
-44
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as React from "react"
2+
import Svg, { Path } from "react-native-svg"
3+
4+
function CheckCircleIcon(props) {
5+
return (
6+
<Svg
7+
width={25}
8+
height={24}
9+
viewBox="0 0 25 24"
10+
fill="none"
11+
xmlns="http://www.w3.org/2000/svg"
12+
{...props}
13+
>
14+
<Path
15+
fillRule="evenodd"
16+
clipRule="evenodd"
17+
d="M12.5 21a9 9 0 100-18 9 9 0 000 18zm4.707-10.293a1 1 0 00-1.414-1.414L11.5 13.586l-2.293-2.293a1 1 0 00-1.414 1.414l2.93 2.93a1.1 1.1 0 001.555 0l4.93-4.93z"
18+
fill="#00B505"
19+
/>
20+
</Svg>
21+
)
22+
}
23+
24+
export default CheckCircleIcon
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as React from "react"
2+
import Svg, { Path } from "react-native-svg"
3+
4+
function PlaceholderIcon(props) {
5+
return (
6+
<Svg
7+
width={24}
8+
height={24}
9+
viewBox="0 0 24 24"
10+
fill="none"
11+
xmlns="http://www.w3.org/2000/svg"
12+
{...props}
13+
>
14+
<Path
15+
fillRule="evenodd"
16+
clipRule="evenodd"
17+
d="M9 5H5v4a1 1 0 01-2 0V4.5A1.5 1.5 0 014.5 3H9a1 1 0 010 2zM5 15a1 1 0 10-2 0v4.5A1.5 1.5 0 004.5 21H9a1 1 0 100-2H5v-4zm9-11a1 1 0 011-1h4.5A1.5 1.5 0 0121 4.5V9a1 1 0 11-2 0V5h-4a1 1 0 01-1-1zm7 11a1 1 0 10-2 0v4h-4a1 1 0 100 2h4.5a1.5 1.5 0 001.5-1.5V15z"
18+
fill="#757575"
19+
/>
20+
</Svg>
21+
)
22+
}
23+
24+
export default PlaceholderIcon
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import * as React from "react";
2+
import { Image, Pressable, StyleSheet, Text, View } from "react-native";
3+
import { colors, paddings, rounded, textStyles } from "../../style";
4+
5+
const CustomCard = ({
6+
iconSource = {},
7+
title,
8+
description,
9+
size = "md", // "md" oder "lg"
10+
state = "default", // State: "active", "default" oder "disabled"
11+
showDescription = true, // Standardmäßig aktiv
12+
onPress
13+
}) => {
14+
// Bestimme den Container-Stil:
15+
// Im active-Zustand wird der aktive Style genutzt,
16+
// In default und disabled wird der Container-Style wie bei disabled angewandt.
17+
const containerStyle =
18+
state === "active"
19+
? size === "md"
20+
? styles.cardMdContainer
21+
: [styles.cardLgContainer, !showDescription && { height: 92}]
22+
: size === "md"
23+
? styles.cardMdDisabled
24+
: [styles.cardLgDisabled, !showDescription && { height: 92}];
25+
26+
// Beim Text: Nur im disabled-Zustand wird durchgestrichen.
27+
const titleStyle = [styles.title, state === "disabled" && styles.strikeThroughText];
28+
const descriptionStyle = [styles.description, state === "disabled" && styles.strikeThroughText];
29+
30+
// Text-Wrapper (für md bzw. lg)
31+
const textWrapperStyle = size === "md" ? styles.textWrapperMd : styles.textWrapperLg;
32+
33+
// Icon: Falls iconSource ein React-Element ist, setzen wir per cloneElement die Farbe auf Schwarz.
34+
const iconElement = React.isValidElement(iconSource)
35+
? React.cloneElement(iconSource, { color: colors.black })
36+
: iconSource;
37+
38+
return (
39+
<Pressable style={containerStyle} onPress={onPress}>
40+
<View style={[styles.iconContainer, size === "lg" && { alignSelf: "flex-start" }]}>
41+
{iconElement}
42+
</View>
43+
<View style={[textWrapperStyle, size === "lg" && { alignSelf: "flex-start" }]}>
44+
<Text style={[titleStyle, {ellipsizeMode: "tail"}]} numberOfLines={1}>
45+
{title}
46+
</Text>
47+
{showDescription && (
48+
<Text style={descriptionStyle} numberOfLines={1}>
49+
{description}
50+
</Text>
51+
)}
52+
</View>
53+
</Pressable>
54+
);;
55+
};
56+
57+
const styles = StyleSheet.create({
58+
// -------------------------------
59+
// Active Styles (voll aktiv)
60+
// -------------------------------
61+
cardMdContainer: {
62+
gap: paddings.p_12,
63+
padding: paddings.p_12,
64+
flexDirection: "row",
65+
alignItems: "center",
66+
backgroundColor: colors.white,
67+
borderStyle: "solid",
68+
borderRadius: rounded.rounded_lg,
69+
width: 160,
70+
height: 64,
71+
borderWidth: 2,
72+
borderColor: colors.black,
73+
},
74+
cardLgContainer: {
75+
gap: paddings.p_16,
76+
padding: paddings.p_16,
77+
alignItems: "center",
78+
backgroundColor: colors.white,
79+
borderStyle: "solid",
80+
borderRadius: rounded.rounded_lg,
81+
width: 160,
82+
height: 112,
83+
borderWidth: 2,
84+
borderColor: colors.black,
85+
},
86+
// -------------------------------
87+
// Disabled Styles (wie bisher)
88+
// -------------------------------
89+
// (Sowohl für default als auch disabled wird hier der Container-Stil genutzt –
90+
// der Unterschied zeigt sich nur beim Text: bei disabled wird der Text durchgestrichen.)
91+
cardMdDisabled: {
92+
gap: paddings.p_12,
93+
padding: paddings.p_12,
94+
flexDirection: "row",
95+
alignItems: "center",
96+
backgroundColor: colors.white,
97+
borderStyle: "solid",
98+
borderRadius: rounded.rounded_lg,
99+
width: 160,
100+
height: 64,
101+
borderWidth: 1,
102+
borderColor: colors.grey200,
103+
},
104+
cardLgDisabled: {
105+
gap: paddings.p_16,
106+
padding: paddings.p_16,
107+
alignItems: "center",
108+
backgroundColor: colors.white,
109+
borderStyle: "solid",
110+
borderRadius: rounded.rounded_lg,
111+
width: 160,
112+
height: 112,
113+
borderWidth: 1,
114+
borderColor: colors.grey200,
115+
116+
},
117+
// -------------------------------
118+
// Icon-Container
119+
// -------------------------------
120+
iconContainer: {
121+
justifyContent: "center",
122+
alignItems: "center",
123+
},
124+
// -------------------------------
125+
// Text Wrapper
126+
// -------------------------------
127+
textWrapperMd: {
128+
width: "100%",
129+
justifyContent: "center",
130+
},
131+
textWrapperLg: {
132+
width: "100%",
133+
justifyContent: "center",
134+
},
135+
// -------------------------------
136+
// Text-Styles
137+
// -------------------------------
138+
title: {
139+
...textStyles.text_sm_semibold,
140+
textAlign: "left",
141+
overflow: "hidden",
142+
alignSelf: "stretch",
143+
},
144+
description: {
145+
...textStyles.text_sm_regular,
146+
color: colors.black,
147+
overflow: "hidden",
148+
alignSelf: "stretch",
149+
},
150+
// Durchgestrichener Text (nur im disabled-Zustand angewandt)
151+
strikeThroughText: {
152+
textDecorationLine: "line-through",
153+
color: colors.grey500,
154+
},
155+
});
156+
157+
export default CustomCard;

src/navigation/AppNavigator.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import BottomNavigationScreen from '../screens/PreviewScreens/bottomNavigationSc
1414
import InputFieldScreen from '../screens/PreviewScreens/inputFieldScreen';
1515
import TopNavigationScreen from '../screens/PreviewScreens/topNavigationScreen';
1616
import NotificationBadgeScreen from '../screens/PreviewScreens/notificationBadgeScreen';
17+
import ButtonIconScreen from '../screens/PreviewScreens/buttonIconScreen';
18+
import CustomCardScreen from '../screens/PreviewScreens/customCardScreen';
1719

1820
// Icons
1921
import HomeIcon from '../../assets/icons/Navigation/homeIcon';
2022
import TemplatesIcon from '../../assets/icons/Navigation/templateIcon';
2123
import SettingsIcon from '../../assets/icons/Navigation/settingsIcon';
2224
import BackIcon from '../../assets/icons/svg_js/backIcon';
23-
import ButtonIconScreen from '../screens/PreviewScreens/buttonIconScreen';
25+
2426

2527
const MainStack = createNativeStackNavigator();
2628

@@ -59,6 +61,7 @@ function MainStackScreen() {
5961
<MainStack.Screen name="InputFieldScreen" component={InputFieldScreen} options={{ title: "Input Field" }} />
6062
<MainStack.Screen name="TopNavigationScreen" component={TopNavigationScreen} options={{ title: "Top Navigation" }} />
6163
<MainStack.Screen name="NotificationBadgeScreen" component={NotificationBadgeScreen} options={{ title: "Notification badge" }} />
64+
<MainStack.Screen name='CustomCardScreen' component={CustomCardScreen} options={{ title: 'Custom Card' }} />
6265
</MainStack.Navigator>
6366
);
6467
}

src/screens/Main/HomeScreen.js

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@ import React from 'react';
22
import { View, Text, StyleSheet, ScrollView } from 'react-native';
33
import { SafeAreaView } from 'react-native-safe-area-context';
44
import { colors, paddings, textStyles } from '../../style';
5-
import ComponentCard from '../../components/common/ComponentCard';
5+
import CustomCard from '../../components/common/CustomCard';
6+
import { useNavigation } from '@react-navigation/native';
7+
import PlaceholderIcon from '../../../assets/icons/svg_js/placeholderIcon';
8+
import CheckCircleIcon from '../../../assets/icons/svg_js/checkCircleIcon';
69

710
export default function HomeScreen() {
11+
const navigation = useNavigation();
12+
13+
const changePage = (screenName) => {
14+
navigation.navigate(screenName);
15+
};
16+
817
return (
918
<SafeAreaView style={styles.container}>
1019
<ScrollView contentContainerStyle={styles.scrollContainer}>
@@ -13,69 +22,76 @@ export default function HomeScreen() {
1322
</View>
1423
<View style={styles.cardsContainer}>
1524
{/* Button */}
16-
<ComponentCard
17-
status={"Complete"}
18-
title={"Button"}
19-
description={"Component"}
20-
screenName={"ButtonScreen"}
25+
<CustomCard
26+
iconSource={<CheckCircleIcon />}
27+
title="Button"
28+
description="Component"
29+
size="lg"
30+
onPress={() => changePage("ButtonScreen")}
2131
/>
2232

2333
{/* Button Icon */}
24-
<ComponentCard
25-
status={"Complete"}
26-
title={"Button Icon"}
27-
description={"Component"}
28-
screenName={"ButtonIconScreen"}
34+
<CustomCard
35+
iconSource={<CheckCircleIcon />}
36+
title="Button Icon"
37+
description="Component"
38+
size="lg"
39+
onPress={() => changePage("ButtonIconScreen")}
2940
/>
3041

3142
{/* Button Dock */}
32-
<ComponentCard
33-
status={"Fehlt"}
34-
title={"Button Dock"}
35-
description={"Component"}
36-
screenName={"ButtonScreen"}
43+
<CustomCard
44+
iconSource={<PlaceholderIcon />}
45+
title="Button Dock"
46+
description="Component"
47+
size="lg"
48+
onPress={() => changePage("ButtonScreen")}
3749
/>
3850

3951
{/* Notification Badge */}
40-
<ComponentCard
41-
status={"Complete"}
42-
title={"Notification badge"}
43-
description={"Component"}
44-
screenName={"NotificationBadgeScreen"}
52+
<CustomCard
53+
iconSource={<CheckCircleIcon />}
54+
title="Notification Badge"
55+
description="Component"
56+
size="lg"
57+
onPress={() => changePage("NotificationBadgeScreen")}
4558
/>
4659

4760
{/* Bottom Navigation */}
48-
<ComponentCard
49-
status={"Complete"}
50-
title={"Bottom Navigation"}
51-
description={"Component"}
52-
screenName={"BottomNavigationScreen"}
61+
<CustomCard
62+
iconSource={<CheckCircleIcon />}
63+
title="Bottom Navigation"
64+
description="Component"
65+
size="lg"
66+
onPress={() => changePage("BottomNavigationScreen")}
5367
/>
5468

5569
{/* Card */}
56-
<ComponentCard
57-
status={"Fehlt"}
58-
title={"Card"}
59-
description={"Component"}
60-
screenName={"BottomNavigationScreen"}
70+
<CustomCard
71+
iconSource={<CheckCircleIcon />}
72+
title="Card"
73+
description="Component"
74+
size="lg"
75+
onPress={() => changePage("CustomCardScreen")}
6176
/>
6277

6378
{/* Input Field */}
64-
<ComponentCard
65-
status={"Complete"}
66-
title={"Input Field"}
67-
description={"Component"}
68-
screenName={"InputFieldScreen"}
79+
<CustomCard
80+
iconSource={<CheckCircleIcon />}
81+
title="Input Field"
82+
description="Component"
83+
size="lg"
84+
onPress={() => changePage("InputFieldScreen")}
6985
/>
7086

7187
{/* Top Navigation */}
72-
<ComponentCard
73-
status={"Complete"}
74-
title={"Top Navigation"}
75-
description={"Component"}
76-
screenName={"TopNavigationScreen"}
88+
<CustomCard
89+
iconSource={<CheckCircleIcon />}
90+
title="Top Navigation"
91+
description="Component"
92+
size="lg"
93+
onPress={() => changePage("TopNavigationScreen")}
7794
/>
78-
7995
</View>
8096
</ScrollView>
8197
</SafeAreaView>
@@ -102,6 +118,7 @@ const styles = StyleSheet.create({
102118
flexDirection: 'row',
103119
flexWrap: 'wrap',
104120
width: '100%',
105-
justifyContent: "space-between",
121+
justifyContent: "space-around",
122+
gap: 16
106123
},
107124
});

0 commit comments

Comments
 (0)