feat : début de EventCard
This commit is contained in:
@@ -26,6 +26,12 @@ export default function HomeTabScreen() {
|
|||||||
onPress={() => router.push('/switch-demo')}
|
onPress={() => router.push('/switch-demo')}
|
||||||
accessibilityLabel="Ouvrir la page de démonstration du switch"
|
accessibilityLabel="Ouvrir la page de démonstration du switch"
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
label="Voir la démo des cards"
|
||||||
|
variant="secondary"
|
||||||
|
onPress={() => router.push('/card-demo')}
|
||||||
|
accessibilityLabel="Ouvrir la page de présentation des cards"
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export default function RootLayout() {
|
|||||||
<Stack.Screen name="(tabs)" />
|
<Stack.Screen name="(tabs)" />
|
||||||
<Stack.Screen name="(org)" />
|
<Stack.Screen name="(org)" />
|
||||||
<Stack.Screen name="switch-demo" />
|
<Stack.Screen name="switch-demo" />
|
||||||
|
<Stack.Screen name="card-demo" />
|
||||||
<Stack.Screen name="event/[id]" />
|
<Stack.Screen name="event/[id]" />
|
||||||
<Stack.Screen name="create/event" options={{ presentation: 'modal' }} />
|
<Stack.Screen name="create/event" options={{ presentation: 'modal' }} />
|
||||||
<Stack.Screen name="create/post" options={{ presentation: 'modal' }} />
|
<Stack.Screen name="create/post" options={{ presentation: 'modal' }} />
|
||||||
|
|||||||
80
src/app/card-demo.tsx
Normal file
80
src/app/card-demo.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
import Card from '@/components/Card';
|
||||||
|
import { Screen } from '@/components/ui/Screen';
|
||||||
|
import { mockEvents } from '@/mocks';
|
||||||
|
import { colors } from '@/theme/colors';
|
||||||
|
import { spacing } from '@/theme/spacing';
|
||||||
|
import { typography } from '@/theme/typography';
|
||||||
|
|
||||||
|
const cardParticipants = [
|
||||||
|
{
|
||||||
|
id: 'lea',
|
||||||
|
source:
|
||||||
|
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=240&q=80',
|
||||||
|
name: 'Lea Martin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'yanis',
|
||||||
|
source:
|
||||||
|
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=240&q=80',
|
||||||
|
name: 'Yanis Belaid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'omar',
|
||||||
|
source:
|
||||||
|
'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?auto=format&fit=crop&w=240&q=80',
|
||||||
|
name: 'Omar Khelifi',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function CardDemoScreen() {
|
||||||
|
const demoEvent = mockEvents[0];
|
||||||
|
|
||||||
|
if (!demoEvent) {
|
||||||
|
return (
|
||||||
|
<Screen contentContainerStyle={styles.content}>
|
||||||
|
<Text style={styles.emptyState}>Aucun événement de démo disponible.</Text>
|
||||||
|
</Screen>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Screen contentContainerStyle={styles.content}>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Text style={styles.kicker}>DESIGN SYSTEM · CARD</Text>
|
||||||
|
<Text style={styles.title}>Page de présentation Card</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
variant="hero"
|
||||||
|
event={demoEvent}
|
||||||
|
avatarStack={cardParticipants}
|
||||||
|
onPress={() => undefined}
|
||||||
|
/>
|
||||||
|
</Screen>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
content: {
|
||||||
|
gap: spacing[16],
|
||||||
|
paddingTop: spacing[24],
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
gap: spacing[8],
|
||||||
|
marginBottom: spacing[8],
|
||||||
|
},
|
||||||
|
kicker: {
|
||||||
|
...typography.sectionLabel,
|
||||||
|
color: colors.textSecondary,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
...typography.body,
|
||||||
|
color: colors.textPrimary,
|
||||||
|
},
|
||||||
|
emptyState: {
|
||||||
|
...typography.body,
|
||||||
|
color: colors.textSecondary,
|
||||||
|
},
|
||||||
|
});
|
||||||
88
src/components/Card.tsx
Normal file
88
src/components/Card.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { Event } from '@/models/events';
|
||||||
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
import { Badge } from './Badge';
|
||||||
|
import { Button } from './Button';
|
||||||
|
import { AvatarStack, AvatarStackItem } from './ui/AvatarStack';
|
||||||
|
|
||||||
|
import { typography } from '@/theme';
|
||||||
|
import { colors } from '@/theme/colors';
|
||||||
|
import { borderRadius } from '@/theme/spacing';
|
||||||
|
|
||||||
|
import { Heart, MapPin } from 'lucide-react-native';
|
||||||
|
|
||||||
|
export type CardVariant = 'hero' | 'list' | 'compact';
|
||||||
|
|
||||||
|
export type CardProps = {
|
||||||
|
variant: CardVariant;
|
||||||
|
event: Event;
|
||||||
|
avatarStack?: AvatarStackItem[];
|
||||||
|
onPress?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Card({
|
||||||
|
variant,
|
||||||
|
event,
|
||||||
|
avatarStack,
|
||||||
|
onPress
|
||||||
|
}: CardProps) {
|
||||||
|
const eventDate = event.start_date;
|
||||||
|
const badgeDate = {
|
||||||
|
day: eventDate.getDate().toString().padStart(2, '0'),
|
||||||
|
month: new Intl.DateTimeFormat('fr-FR', { month: 'short' })
|
||||||
|
.format(eventDate)
|
||||||
|
.replace('.', ''),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={styles.card}
|
||||||
|
>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Badge variant='date' date={badgeDate} />
|
||||||
|
<Button variant='ghost' icon={Heart} iconOnly onPress={onPress} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.content}>
|
||||||
|
<Badge variant='tonight' label='CE SOIR' />
|
||||||
|
<Text style={styles.title}>
|
||||||
|
{event.name}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.subtitle}>
|
||||||
|
<MapPin size={16} color={colors.textBody} />{' '}
|
||||||
|
{event.address}, {event.city} - 18 km
|
||||||
|
</Text>
|
||||||
|
{avatarStack && <AvatarStack items={avatarStack} />}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
card: {
|
||||||
|
borderRadius: borderRadius.card,
|
||||||
|
backgroundColor: colors.surface,
|
||||||
|
height: 230,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 3,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
...typography.cardTitle,
|
||||||
|
color: colors.textPrimary,
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
...typography.label,
|
||||||
|
color: colors.textBody
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Card;
|
||||||
@@ -9,8 +9,6 @@ export const theme = {
|
|||||||
borderRadius,
|
borderRadius,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export * from './ThemeProvider';
|
|
||||||
export * from './useTheme';
|
|
||||||
export { borderRadius, colors, spacing, typography };
|
export { borderRadius, colors, spacing, typography };
|
||||||
|
|
||||||
export default theme;
|
export default theme;
|
||||||
|
|||||||
Reference in New Issue
Block a user