Livrare Lot 3 (Frontend): aplicație web, aplicație mobilă Android, extensie browser
- Surse complete web (React/Vite) + mobil (React Native/Expo) + extensie (MV3) - Documentație de livrare: ghid utilizare, matrice trasabilitate cerințe, raport testare furnizor - Artefacte binare: imagine Docker didi-frontend:lot3-1.0, APK, extensie v3.2.6 + SHA256SUMS - Configurare adresă platformă externalizată (build args / .env / config.js) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
cec967f953
321 changed files with 80506 additions and 0 deletions
105
android/didi-app-source/src/components/GlassCard.tsx
Normal file
105
android/didi-app-source/src/components/GlassCard.tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import React from 'react';
|
||||
import { View, TouchableOpacity, Text, StyleSheet, ViewStyle } from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { COLORS, SPACING, RADIUS, FONT_SIZES, FONT_WEIGHTS, LAYOUT } from '../theme/colors';
|
||||
|
||||
interface GlassCardProps {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
iconLabel?: string;
|
||||
iconColors?: readonly [string, string];
|
||||
onPress?: () => void;
|
||||
style?: ViewStyle;
|
||||
borderColor?: string;
|
||||
}
|
||||
|
||||
export default function GlassCard({
|
||||
title,
|
||||
subtitle,
|
||||
iconLabel,
|
||||
iconColors,
|
||||
onPress,
|
||||
style,
|
||||
borderColor,
|
||||
}: GlassCardProps) {
|
||||
const Wrapper = onPress ? TouchableOpacity : View;
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
activeOpacity={0.7}
|
||||
onPress={onPress}
|
||||
accessibilityRole={onPress ? 'button' : undefined}
|
||||
accessibilityLabel={onPress ? `${title}. ${subtitle}` : undefined}
|
||||
style={[
|
||||
styles.card,
|
||||
borderColor ? { borderColor } : undefined,
|
||||
style,
|
||||
]}
|
||||
>
|
||||
<View style={styles.content}>
|
||||
{iconLabel && (
|
||||
<LinearGradient
|
||||
colors={iconColors ? [...iconColors] as [string, string] : [COLORS.brand.primary, COLORS.brand.accentMagenta]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.iconCircle}
|
||||
>
|
||||
<Text style={styles.iconText}>{iconLabel}</Text>
|
||||
</LinearGradient>
|
||||
)}
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.title}>{title}</Text>
|
||||
<Text style={styles.subtitle}>{subtitle}</Text>
|
||||
</View>
|
||||
{onPress && <Text style={styles.arrow}>›</Text>}
|
||||
</View>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
backgroundColor: COLORS.bg.card,
|
||||
borderWidth: 1,
|
||||
borderColor: COLORS.border.accent,
|
||||
borderRadius: RADIUS.xxl,
|
||||
padding: SPACING.lg,
|
||||
marginBottom: SPACING.sm + 4,
|
||||
},
|
||||
content: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
iconCircle: {
|
||||
width: LAYOUT.ICON_CIRCLE_SIZE,
|
||||
height: LAYOUT.ICON_CIRCLE_SIZE,
|
||||
borderRadius: RADIUS.full,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: SPACING.md,
|
||||
},
|
||||
iconText: {
|
||||
color: COLORS.text.primary,
|
||||
fontSize: FONT_SIZES.lg,
|
||||
fontWeight: FONT_WEIGHTS.bold,
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.text.primary,
|
||||
fontSize: FONT_SIZES.base,
|
||||
fontWeight: FONT_WEIGHTS.bold,
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.text.secondary,
|
||||
fontSize: FONT_SIZES.sm,
|
||||
marginTop: 2,
|
||||
},
|
||||
arrow: {
|
||||
color: COLORS.text.hint,
|
||||
fontSize: FONT_SIZES.xxl,
|
||||
fontWeight: FONT_WEIGHTS.bold,
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue