feat(my-plants): grouped card style for date groups
Aligne le rendu des date groups sur le pattern PracticalGuides : items encapsulés dans une card blanche rounded-16, séparés par une ligne grise indentée. - ScanListItem : nouvelles props grouped + showSeparator → désactive borderRadius/margins/border individuels et active la ligne séparatrice alignée sous le texte - DateGroupAccordion : wrappe les ScanListItem dans une View card avec shadow iOS / elevation Android Le même pattern est réutilisé par RecentScans (Home) — voir commit suivant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3781b1c0f4
commit
4ebbc692ff
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
|
import { View, TouchableOpacity, Text, StyleSheet, Platform } from 'react-native';
|
||||||
import Animated, {
|
import Animated, {
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
useSharedValue,
|
useSharedValue,
|
||||||
|
|
@ -63,15 +63,19 @@ export function DateGroupAccordion({
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
{scans.map((scan) => (
|
<View style={styles.card}>
|
||||||
<ScanListItem
|
{scans.map((scan, index) => (
|
||||||
key={scan.id}
|
<ScanListItem
|
||||||
scan={scan}
|
key={scan.id}
|
||||||
onPress={() => onPressScan(scan)}
|
scan={scan}
|
||||||
onToggleFavorite={() => onToggleFavorite(scan.id)}
|
onPress={() => onPressScan(scan)}
|
||||||
onDelete={() => onDeleteScan(scan.id)}
|
onToggleFavorite={() => onToggleFavorite(scan.id)}
|
||||||
/>
|
onDelete={() => onDeleteScan(scan.id)}
|
||||||
))}
|
grouped
|
||||||
|
showSeparator={index < scans.length - 1}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -107,7 +111,24 @@ const styles = StyleSheet.create({
|
||||||
color: '#8E8E93',
|
color: '#8E8E93',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
paddingTop: 4,
|
paddingTop: 8,
|
||||||
paddingBottom: 8,
|
paddingBottom: 8,
|
||||||
|
paddingHorizontal: 20,
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
borderRadius: 16,
|
||||||
|
overflow: 'hidden',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '#F0F0F0',
|
||||||
|
...Platform.select({
|
||||||
|
ios: {
|
||||||
|
shadowColor: '#000',
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.04,
|
||||||
|
shadowRadius: 8,
|
||||||
|
},
|
||||||
|
android: { elevation: 2 },
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ interface ScanListItemProps {
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
onToggleFavorite: () => void;
|
onToggleFavorite: () => void;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
|
grouped?: boolean;
|
||||||
|
showSeparator?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const STATUS_FILL: Record<ScanStatus, string> = {
|
const STATUS_FILL: Record<ScanStatus, string> = {
|
||||||
|
|
@ -46,7 +48,14 @@ function getPlantName(scan: ScanRecord, t: (key: string) => string): string {
|
||||||
return t('result.notVine');
|
return t('result.notVine');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScanListItem({ scan, onPress, onToggleFavorite, onDelete }: ScanListItemProps) {
|
export function ScanListItem({
|
||||||
|
scan,
|
||||||
|
onPress,
|
||||||
|
onToggleFavorite,
|
||||||
|
onDelete,
|
||||||
|
grouped = false,
|
||||||
|
showSeparator = false,
|
||||||
|
}: ScanListItemProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const swipeableRef = useRef<Swipeable>(null);
|
const swipeableRef = useRef<Swipeable>(null);
|
||||||
const isFav = scan.isFavorite === true;
|
const isFav = scan.isFavorite === true;
|
||||||
|
|
@ -117,7 +126,7 @@ export function ScanListItem({ scan, onPress, onToggleFavorite, onDelete }: Scan
|
||||||
friction={2}
|
friction={2}
|
||||||
>
|
>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.container}
|
style={[styles.container, grouped && styles.containerGrouped]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
hapticLight();
|
hapticLight();
|
||||||
onPress();
|
onPress();
|
||||||
|
|
@ -160,6 +169,7 @@ export function ScanListItem({ scan, onPress, onToggleFavorite, onDelete }: Scan
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
{grouped && showSeparator && <View style={styles.separator} />}
|
||||||
</Swipeable>
|
</Swipeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -176,6 +186,19 @@ const styles = StyleSheet.create({
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: '#F0F0F0',
|
borderColor: '#F0F0F0',
|
||||||
},
|
},
|
||||||
|
containerGrouped: {
|
||||||
|
borderRadius: 0,
|
||||||
|
marginHorizontal: 0,
|
||||||
|
marginVertical: 0,
|
||||||
|
borderWidth: 0,
|
||||||
|
paddingVertical: 14,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: '#F0F0F0',
|
||||||
|
marginLeft: 92,
|
||||||
|
},
|
||||||
imageWrapper: {
|
imageWrapper: {
|
||||||
width: 64,
|
width: 64,
|
||||||
height: 64,
|
height: 64,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue