Skip to content

Commit 25e360d

Browse files
authored
Trend is now style brrraa (#75)
1 parent 992d466 commit 25e360d

6 files changed

Lines changed: 117 additions & 21 deletions

File tree

mobile/app/(tabs)/trends/[trendId].tsx

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { useLocalSearchParams } from 'expo-router';
2-
import { Alert, Button, ScrollView, Share, StyleSheet, Text, View } from 'react-native';
2+
import { Alert, Pressable, ScrollView, Share, StyleSheet, Text, View } from 'react-native';
33

44
import CustomSafeAreaView from '@/components/CustomSafeAreaView';
55
import { Image } from 'expo-image';
66
import Ionicons from '@expo/vector-icons/Ionicons';
77
import { useEffect, useState } from 'react';
88
import { fetchTrend, Trend } from '@/utils/trendApi';
9+
import SectionHeader from '@/components/SectionHeader';
10+
import { Colors } from '@/constants/Colors';
911

1012
export default function TrendDetail() {
1113
const { trendId } = useLocalSearchParams();
@@ -23,7 +25,7 @@ export default function TrendDetail() {
2325
});
2426
}, [trendId]);
2527

26-
const onShare = async () => {
28+
const handleShare = async () => {
2729
try {
2830
const result = await Share.share({
2931
message: `Check out this trend!
@@ -50,25 +52,45 @@ _found with GetDressed ✨_`,
5052

5153
return (
5254
<CustomSafeAreaView style={styles.container}>
53-
<ScrollView>
55+
<SectionHeader title={trend?.trendTitle || 'Aktueller Trend'} />
56+
<Pressable onPress={handleShare} style={styles.floatingShare}>
57+
<Ionicons name="share" size={24} style={styles.floatingText} />
58+
</Pressable>
59+
<ScrollView style={styles.scrollContainer} showsVerticalScrollIndicator={false}>
5460
<View style={{ marginBottom: 24 }}>
61+
<Image source={trend?.trendImage} style={styles.image} />
5562
<Text style={styles.title}>Aktueller Trend:</Text>
5663
<Text style={styles.title}>{trend?.trendTitle}</Text>
57-
<Image source={trend?.trendImage} style={styles.image} />
5864
</View>
5965
<View style={{ marginBottom: 24 }}>
60-
<Text style={styles.title}>Hype auf Instagram</Text>
6166
<Text style={styles.text}>{trend?.trendDescription}</Text>
6267
</View>
6368
<View style={{ marginBottom: 24 }}>
6469
<Text style={styles.text}>found on:</Text>
6570
<View style={{ flexDirection: 'row' }}>
66-
<Ionicons style={styles.socialIcon} name="logo-instagram" size={24} color="#999" />
67-
<Ionicons style={styles.socialIcon} name="logo-pinterest" size={24} color="#999" />
68-
<Ionicons style={styles.socialIcon} name="logo-twitter" size={24} color="#999" />
71+
{trend?.trendSources?.map((source) => {
72+
// Map known sources to valid Ionicons names
73+
const iconMap: { [key: string]: keyof typeof Ionicons.glyphMap } = {
74+
Instagram: 'logo-instagram',
75+
Facebook: 'logo-facebook',
76+
Twitter: 'logo-twitter',
77+
TikTok: 'logo-tiktok',
78+
Pinterest: 'logo-pinterest',
79+
// add more mappings as needed
80+
};
81+
const iconName = iconMap[source] || 'help';
82+
return (
83+
<Ionicons
84+
style={styles.socialIcon}
85+
name={iconName}
86+
size={24}
87+
color="#999"
88+
key={source}
89+
/>
90+
);
91+
})}
6992
</View>
7093
</View>
71-
<Button onPress={onShare} title="Share" />
7294
</ScrollView>
7395
</CustomSafeAreaView>
7496
);
@@ -77,10 +99,12 @@ _found with GetDressed ✨_`,
7799
const styles = StyleSheet.create({
78100
container: {
79101
flex: 1,
80-
paddingTop: 32,
81-
paddingHorizontal: 16,
82102
backgroundColor: '#fff',
83103
},
104+
scrollContainer: {
105+
marginTop: 24,
106+
paddingHorizontal: 16,
107+
},
84108
title: {
85109
fontSize: 22,
86110
fontWeight: 'bold',
@@ -92,10 +116,24 @@ const styles = StyleSheet.create({
92116
},
93117
text: {
94118
marginBottom: 16,
95-
fontWeight: 'bold',
96119
color: '#999',
97120
},
98121
socialIcon: {
99122
marginRight: 16,
100123
},
124+
floatingShare: {
125+
position: 'absolute',
126+
zIndex: 100,
127+
right: 16,
128+
bottom: 22,
129+
width: 50,
130+
height: 50,
131+
backgroundColor: Colors.light.shareButton,
132+
borderRadius: 25,
133+
justifyContent: 'center',
134+
alignItems: 'center',
135+
},
136+
floatingText: {
137+
color: '#fff',
138+
},
101139
});

mobile/app/(tabs)/trends/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import CustomSafeAreaView from '@/components/CustomSafeAreaView';
2+
import SectionHeader from '@/components/SectionHeader';
23
import TrendList from '@/components/TrendList';
34
import TrendPrompt from '@/components/TrendPrompt';
45
import { StyleSheet, Text, View } from 'react-native';
56

67
export default function TrendScout() {
78
return (
89
<CustomSafeAreaView style={styles.container}>
10+
<SectionHeader title="Trend-Scout" />
911
<View style={styles.promptContainer}>
1012
<Text style={styles.title}>Frag den Trend-Scout</Text>
1113
<Text style={styles.text}>
@@ -25,15 +27,16 @@ export default function TrendScout() {
2527
const styles = StyleSheet.create({
2628
container: {
2729
flex: 1,
28-
paddingHorizontal: 16,
2930
backgroundColor: '#fff',
30-
paddingTop: 32,
3131
},
3232
promptContainer: {
33-
marginBottom: 24,
33+
marginTop: 24,
34+
paddingHorizontal: 16,
3435
},
3536
trendsContainer: {
3637
flex: 1,
38+
marginTop: 24,
39+
paddingHorizontal: 16,
3740
},
3841
title: {
3942
fontSize: 22,
@@ -42,7 +45,6 @@ const styles = StyleSheet.create({
4245
},
4346
text: {
4447
marginBottom: 16,
45-
fontWeight: 'bold',
4648
color: '#999',
4749
},
4850
});

mobile/components/TrendList.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default function TrendList() {
3434
renderItem={({ item }) => <TrendListItem trend={item} />}
3535
keyExtractor={(item) => item.trendId}
3636
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
37+
showsVerticalScrollIndicator={false}
3738
/>
3839
</View>
3940
);

mobile/components/TrendPrompt.tsx

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,54 @@
11
import { generateTrends, saveTrends } from '@/utils/trendApi';
22
import Ionicons from '@expo/vector-icons/Ionicons';
3-
import { useState } from 'react';
4-
import { ActivityIndicator, Pressable, StyleSheet, TextInput, View } from 'react-native';
3+
import { useEffect, useState } from 'react';
4+
import {
5+
Animated,
6+
Easing,
7+
Pressable,
8+
StyleSheet,
9+
TextInput,
10+
useAnimatedValue,
11+
View,
12+
} from 'react-native';
513

614
export default function TrendPrompt() {
715
const [prompt, setPrompt] = useState<string>('');
816
const [isThinking, setIsThinking] = useState<boolean>(false);
17+
const rotateValue = useAnimatedValue(0);
18+
19+
useEffect(() => {
20+
const flipLoop = () => {
21+
Animated.sequence([
22+
Animated.timing(rotateValue, {
23+
toValue: 1,
24+
duration: 800,
25+
easing: Easing.inOut(Easing.ease),
26+
useNativeDriver: true,
27+
}),
28+
Animated.delay(500), // pause after flip
29+
Animated.timing(rotateValue, {
30+
toValue: 0,
31+
duration: 800,
32+
easing: Easing.inOut(Easing.ease),
33+
useNativeDriver: true,
34+
}),
35+
Animated.delay(500), // pause after flipping back
36+
]).start(() => flipLoop());
37+
};
38+
39+
flipLoop();
40+
}, [rotateValue]);
41+
42+
const rotateInterpolate = rotateValue.interpolate({
43+
inputRange: [0, 1],
44+
outputRange: ['0deg', '180deg'],
45+
});
46+
47+
const animatedStyle = {
48+
transform: [{ rotate: rotateInterpolate }],
49+
};
50+
51+
const AnimatedIcon = Animated.createAnimatedComponent(Ionicons);
952

1053
const handleSubmit = async () => {
1154
setIsThinking(true);
@@ -24,23 +67,29 @@ export default function TrendPrompt() {
2467
return (
2568
<View>
2669
<View style={styles.inputContainer}>
70+
{isThinking && (
71+
<AnimatedIcon
72+
name="hourglass-outline"
73+
size={24}
74+
style={[styles.thinkingIdicator, animatedStyle]}
75+
/>
76+
)}
2777
<TextInput
2878
style={styles.input}
2979
enterKeyHint="search"
3080
maxLength={200}
3181
multiline
3282
textAlignVertical="top"
3383
submitBehavior="blurAndSubmit"
34-
placeholder="Welche Sneakers sind bei Stars gerade angesagt?"
3584
value={prompt}
3685
onChangeText={setPrompt}
3786
onSubmitEditing={handleSubmit}
87+
editable={!isThinking}
3888
/>
39-
<Pressable onPress={handleSubmit}>
89+
<Pressable onPress={handleSubmit} disabled={isThinking}>
4090
<Ionicons name="send" size={24} />
4191
</Pressable>
4292
</View>
43-
{isThinking && <ActivityIndicator />}
4493
</View>
4594
);
4695
}
@@ -57,4 +106,7 @@ const styles = StyleSheet.create({
57106
padding: 14,
58107
backgroundColor: '#f3f3f3',
59108
},
109+
thinkingIdicator: {
110+
color: '#999',
111+
},
60112
});

mobile/constants/Colors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ export const Colors = {
88
light: {
99
background: neutralColor,
1010
tabBarIconActive: tertiaryColor,
11+
shareButton: primaryColor,
1112
},
1213
dark: {
1314
background: neutralColor,
1415
tabBarIconActive: tertiaryColor,
16+
shareButton: primaryColor,
1517
},
1618
};

mobile/utils/trendApi.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const fetchTrend = async (trendId: string): Promise<Trend | undefined> =>
1616
trendTitle: trendData.title,
1717
trendDescription: trendData.description,
1818
trendImage: pb.files.getURL(trendData, trendData.image),
19+
trendSources: trendData.sources ? (trendData.sources as string[]) : [],
1920
};
2021
return formattedTrend;
2122
} catch (error) {

0 commit comments

Comments
 (0)