From d39c49cce6f2de9c67f0abb2bde331cd56fbd4ae Mon Sep 17 00:00:00 2001 From: Xor290 Date: Sun, 26 Apr 2026 19:07:26 +0200 Subject: [PATCH] chore: fix UI --- .../src/screens/admin/DashboardScreen.tsx | 28 ++++--- .../src/screens/admin/DeliveryScreen.tsx | 22 +++-- .../src/screens/admin/OrderDetailScreen.tsx | 7 +- .../src/screens/admin/SettingsScreen.tsx | 35 ++++---- .../src/screens/admin/UsersScreen.tsx | 82 +++++++++++-------- .../src/screens/auth/AdminLoginScreen.tsx | 31 ++++--- .../src/screens/auth/CabineLoginScreen.tsx | 31 ++++--- .../src/screens/auth/DeliveryLoginScreen.tsx | 31 ++++--- .../src/screens/cabine/DashboardScreen.tsx | 28 ++++--- .../src/screens/delivery/DashboardScreen.tsx | 24 +++--- 10 files changed, 172 insertions(+), 147 deletions(-) diff --git a/frontend-admin/src/screens/admin/DashboardScreen.tsx b/frontend-admin/src/screens/admin/DashboardScreen.tsx index acf37fb5..a59791a7 100644 --- a/frontend-admin/src/screens/admin/DashboardScreen.tsx +++ b/frontend-admin/src/screens/admin/DashboardScreen.tsx @@ -8,6 +8,7 @@ import { TouchableOpacity, Linking, Alert, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; @@ -35,6 +36,7 @@ interface StatCard { export default function DashboardScreen() { const { colors } = useTheme(); const { username } = useAuth(); + const { width: screenWidth } = useWindowDimensions(); const [stats, setStats] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); @@ -137,54 +139,54 @@ export default function DashboardScreen() { container: { flex: 1, backgroundColor: colors.bgPrimary, - padding: spacing.l, + padding: screenWidth < 380 ? spacing.m : spacing.l, }, welcome: { - fontSize: fontSize.xl, + fontSize: screenWidth < 380 ? fontSize.lg : fontSize.xl, fontWeight: "bold", color: colors.textWhite, marginBottom: spacing.xs, }, subtitle: { - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textSecondary, - marginBottom: spacing.xl, + marginBottom: spacing.l, }, grid: { flexDirection: "row", flexWrap: "wrap", - gap: spacing.m, + gap: screenWidth < 380 ? spacing.s : spacing.m, }, card: { - width: "47%", + width: screenWidth < 360 ? "100%" : "47%", backgroundColor: colors.bgCard, borderRadius: borderRadius.md, - padding: spacing.l, + padding: screenWidth < 380 ? spacing.m : spacing.l, borderWidth: 1, borderColor: colors.borderLight, alignItems: "center", }, iconCircle: { - width: 48, - height: 48, - borderRadius: 24, + width: screenWidth < 380 ? 40 : 48, + height: screenWidth < 380 ? 40 : 48, + borderRadius: screenWidth < 380 ? 20 : 24, justifyContent: "center", alignItems: "center", marginBottom: spacing.s, }, cardValue: { - fontSize: fontSize.xxl, + fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "bold", color: colors.textWhite, }, cardLabel: { - fontSize: fontSize.sm, + fontSize: screenWidth < 380 ? fontSize.xs : fontSize.sm, color: colors.textSecondary, marginTop: spacing.xs, textAlign: "center", }, }), - [colors], + [colors, screenWidth], ); if (loading) return ; diff --git a/frontend-admin/src/screens/admin/DeliveryScreen.tsx b/frontend-admin/src/screens/admin/DeliveryScreen.tsx index ec88b18a..f23028e3 100644 --- a/frontend-admin/src/screens/admin/DeliveryScreen.tsx +++ b/frontend-admin/src/screens/admin/DeliveryScreen.tsx @@ -14,6 +14,7 @@ import { TouchableOpacity, Modal, StatusBar, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; @@ -34,10 +35,10 @@ import TomTomMap, { TomTomMarker, } from "../../components/TomTomMap"; -const MAP_HEIGHT = 280; - export default function DeliveryScreen() { const { colors } = useTheme(); + const { width: screenWidth, height: screenHeight } = useWindowDimensions(); + const MAP_HEIGHT = screenHeight < 700 ? 200 : screenWidth < 380 ? 220 : 280; const statusColors = getStatusColors(colors); const [livreurs, setLivreurs] = useState([]); const [stats, setStats] = useState({ @@ -185,8 +186,8 @@ export default function DeliveryScreen() { summaryRow: { flexDirection: "row", - padding: spacing.l, - gap: spacing.s, + padding: screenWidth < 380 ? spacing.m : spacing.l, + gap: screenWidth < 380 ? spacing.xs : spacing.s, }, summaryCard: { flex: 1, @@ -197,13 +198,14 @@ export default function DeliveryScreen() { alignItems: "center", }, summaryValue: { - fontSize: fontSize.xl, + fontSize: screenWidth < 380 ? fontSize.lg : fontSize.xl, fontWeight: "bold", color: colors.textWhite, }, summaryLabel: { - fontSize: fontSize.xs, + fontSize: screenWidth < 380 ? 10 : fontSize.xs, color: colors.textMuted, + textAlign: "center", }, mapContainer: { @@ -311,7 +313,8 @@ export default function DeliveryScreen() { }, statsRow: { flexDirection: "row", - gap: spacing.l, + flexWrap: "wrap", + gap: screenWidth < 380 ? spacing.s : spacing.l, marginTop: spacing.s, }, stat: { @@ -425,8 +428,9 @@ export default function DeliveryScreen() { }, legendRow: { flexDirection: "row", + flexWrap: "wrap", justifyContent: "center", - gap: spacing.l, + gap: screenWidth < 380 ? spacing.m : spacing.l, }, legendItem: { flexDirection: "row", @@ -436,7 +440,7 @@ export default function DeliveryScreen() { legendDot: { width: 10, height: 10, borderRadius: 5 }, legendText: { color: colors.white, fontSize: fontSize.sm }, }), - [colors], + [colors, screenWidth, screenHeight, MAP_HEIGHT], ); // -------------------------------------------------- diff --git a/frontend-admin/src/screens/admin/OrderDetailScreen.tsx b/frontend-admin/src/screens/admin/OrderDetailScreen.tsx index e802736f..e4aff189 100644 --- a/frontend-admin/src/screens/admin/OrderDetailScreen.tsx +++ b/frontend-admin/src/screens/admin/OrderDetailScreen.tsx @@ -8,6 +8,7 @@ import { Modal, StatusBar, Alert, + useWindowDimensions, } from "react-native"; import { useRoute, @@ -41,10 +42,10 @@ import { useAlert } from "../../hooks/useAlert"; type Route = RouteProp; -const MAP_HEIGHT = 240; - export default function OrderDetailScreen() { const { colors } = useTheme(); + const { height: screenHeight } = useWindowDimensions(); + const MAP_HEIGHT = screenHeight < 700 ? 180 : 240; const route = useRoute(); const navigation = useNavigation(); const { orderId } = route.params; @@ -472,7 +473,7 @@ export default function OrderDetailScreen() { fontWeight: "700", }, }), - [colors], + [colors, MAP_HEIGHT], ); if (loading) return ; diff --git a/frontend-admin/src/screens/admin/SettingsScreen.tsx b/frontend-admin/src/screens/admin/SettingsScreen.tsx index bdd8396d..95d9d6db 100644 --- a/frontend-admin/src/screens/admin/SettingsScreen.tsx +++ b/frontend-admin/src/screens/admin/SettingsScreen.tsx @@ -9,6 +9,7 @@ import { ActivityIndicator, TextInput, Keyboard, + useWindowDimensions, } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { Ionicons } from "@expo/vector-icons"; @@ -101,7 +102,7 @@ function DeliveryScheduleSection({ Ouverture updateDay(key, { open_time: v })} placeholder="09:00" @@ -112,7 +113,7 @@ function DeliveryScheduleSection({ Fermeture updateDay(key, { close_time: v })} placeholder="20:00" @@ -240,7 +241,7 @@ function PostalZonesSection({ {/* Nom */} - Nom + Nom {/* Minimum */} - Min € + Min € { const n = parseFloat(v); @@ -332,7 +333,7 @@ function PostalZonesSection({ Montant minimum de commande (€) * { setForm((f) => ({ ...f, min_amount: v })); setFormError(""); }} keyboardType="decimal-pad" @@ -564,9 +565,9 @@ function TiersSection({ {/* En-tête colonnes */} - Min € - Max € - Pts + Min € + Max € + Pts {tiers.map((tier, i) => ( @@ -583,14 +584,14 @@ function TiersSection({ }} > updateTier(i, "min", v)} /> updateTier(i, "max", v)} @@ -599,7 +600,7 @@ function TiersSection({ /> = updateTier(i, "points", v)} @@ -640,6 +641,10 @@ export default function SettingsScreen() { const { colors } = useTheme(); const { alert, showError, showSuccess, hideAlert } = useAlert(); const navigation = useNavigation(); + const { width: screenWidth } = useWindowDimensions(); + const inputSm = screenWidth < 380 ? 46 : 56; + const inputMd = screenWidth < 380 ? 64 : 80; + const inputLg = screenWidth < 380 ? 80 : 100; const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); @@ -811,7 +816,7 @@ export default function SettingsScreen() { const s = StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bgPrimary }, - content: { padding: spacing.l, paddingBottom: spacing.xl * 2 }, + content: { padding: screenWidth < 380 ? spacing.m : spacing.l, paddingBottom: spacing.xl * 2 }, section: { backgroundColor: colors.bgSecondary, borderRadius: borderRadius.lg, @@ -988,7 +993,7 @@ export default function SettingsScreen() { À partir de (annul.) - Montant + Montant {settings.penalty_tiers.map((tier, i) => ( @@ -1008,7 +1013,7 @@ export default function SettingsScreen() { placeholderTextColor={colors.textMuted} /> { const n = parseInt(v, 10); diff --git a/frontend-admin/src/screens/admin/UsersScreen.tsx b/frontend-admin/src/screens/admin/UsersScreen.tsx index 80221821..3a18241e 100644 --- a/frontend-admin/src/screens/admin/UsersScreen.tsx +++ b/frontend-admin/src/screens/admin/UsersScreen.tsx @@ -9,6 +9,7 @@ import { TouchableOpacity, TextInput as RNTextInput, ActivityIndicator, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; @@ -58,6 +59,7 @@ type RoleFilter = "all" | "client" | "livreur" | "cabine" | "admin"; // ================================================== export default function UsersScreen() { const { colors } = useTheme(); + const { width: screenWidth } = useWindowDimensions(); const ROLE_TABS: { key: RoleFilter; @@ -487,6 +489,8 @@ export default function UsersScreen() { setAmendeReason(""); if (res.compensated) { showSuccess("Compensation", "Amende annulée — solde parrainage débité en compensation"); + } else { + showSuccess("Validé", `Amende de ${pts} € appliquée à "${sanctionModal.client!.username}"`); } await loadData(); }, @@ -501,6 +505,7 @@ export default function UsersScreen() { async () => { const res = await resetClientPenalties(sanctionModal.client!.username, false); if (!res.success) { showError("Erreur", res.error || "Echec"); return; } + showSuccess("Validé", `Amende de "${sanctionModal.client!.username}" remise à zéro`); await loadData(); }, "Remettre à zéro", @@ -523,6 +528,7 @@ export default function UsersScreen() { setPointsLoading((prev) => ({ ...prev, [poolKey]: false })); if (!res.success) { showError("Erreur", res.error || "Echec"); return; } setPointsInputs((prev) => ({ ...prev, [poolKey]: "" })); + showSuccess("Validé", `${pts} points "${poolName}" ajoutés à "${sanctionModal.client!.username}"`); await loadData(); }, ); @@ -544,6 +550,7 @@ export default function UsersScreen() { setSubtractLoading((prev) => ({ ...prev, [poolKey]: false })); if (!res.success) { showError("Erreur", res.error || "Echec"); return; } setSubtractInputs((prev) => ({ ...prev, [poolKey]: "" })); + showSuccess("Validé", `${pts} points "${poolName}" retirés à "${sanctionModal.client!.username}"`); await loadData(); }, ); @@ -557,6 +564,7 @@ export default function UsersScreen() { async () => { const res = await resetClientPoints(sanctionModal.client!.username, poolIdx); if (!res.success) { showError("Erreur", res.error || "Echec"); return; } + showSuccess("Validé", `Points "${poolName}" de "${sanctionModal.client!.username}" remis à zéro`); await loadData(); }, "Remettre à zéro", @@ -675,36 +683,38 @@ export default function UsersScreen() { // Filter grid filterGrid: { flexDirection: "row", - paddingHorizontal: spacing.m, - paddingVertical: spacing.m, - gap: spacing.s, + paddingHorizontal: screenWidth < 380 ? spacing.s : spacing.m, + paddingVertical: spacing.s, + gap: screenWidth < 380 ? spacing.xs : spacing.s, }, filterCard: { flex: 1, alignItems: "center", - paddingVertical: spacing.m, + paddingVertical: spacing.s, + paddingHorizontal: 2, borderRadius: borderRadius.md, borderWidth: 1, borderColor: colors.border, backgroundColor: colors.bgSecondary, }, filterIconCircle: { - width: 36, - height: 36, - borderRadius: 18, + width: screenWidth < 380 ? 28 : 36, + height: screenWidth < 380 ? 28 : 36, + borderRadius: screenWidth < 380 ? 14 : 18, justifyContent: "center", alignItems: "center", - marginBottom: 4, + marginBottom: 2, }, filterCount: { color: colors.textWhite, - fontSize: fontSize.lg, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, fontWeight: "700", }, filterLabel: { color: colors.textMuted, - fontSize: fontSize.sm, + fontSize: screenWidth < 380 ? 10 : fontSize.xs, fontWeight: "600", + textAlign: "center", }, // Card @@ -754,17 +764,23 @@ export default function UsersScreen() { }, statsRow: { flexDirection: "row", - marginTop: spacing.m, - gap: spacing.l, + flexWrap: "wrap", + marginTop: spacing.s, + gap: spacing.s, marginLeft: 52, }, - stat: { alignItems: "center" }, + stat: { + alignItems: "center", + minWidth: 52, + paddingVertical: spacing.xs, + }, statValue: { - fontSize: fontSize.md, + fontSize: fontSize.sm, fontWeight: "bold", color: colors.textWhite, + textAlign: "center", }, - statLabel: { fontSize: fontSize.xs, color: colors.textMuted }, + statLabel: { fontSize: fontSize.xs, color: colors.textMuted, textAlign: "center" }, // Non-client nonClientInfo: { @@ -846,7 +862,7 @@ export default function UsersScreen() { fontWeight: "600", }, }), - [colors], + [colors, screenWidth], ); // -------------------------------------------------- @@ -991,10 +1007,10 @@ export default function UsersScreen() { - + {item.clientData.command} - Cmd + Cmd {pointsEnabled && poolNames.map((name, i) => { const key = poolKeys[i] ?? ""; @@ -1002,46 +1018,40 @@ export default function UsersScreen() { const color = i === 0 ? colors.success : i === 1 ? colors.info : colors.warning; return ( - {value} - {name} + {value} + {name} ); })} {amendeEnabled && ( - {item.clientData.amende} € + {item.clientData.amende}€ - Amende + Amende )} {item.clientData.cancellations_count} - Annul. + Annul. {referralEnabled && (item.clientData.referral_balance ?? 0) > 0 && ( {(item.clientData.referral_balance ?? 0).toFixed(0)}€ - Parrain + Parrain )} diff --git a/frontend-admin/src/screens/auth/AdminLoginScreen.tsx b/frontend-admin/src/screens/auth/AdminLoginScreen.tsx index fc6a4d27..837fe69e 100644 --- a/frontend-admin/src/screens/auth/AdminLoginScreen.tsx +++ b/frontend-admin/src/screens/auth/AdminLoginScreen.tsx @@ -8,7 +8,7 @@ import { TouchableOpacity, TextInput as RNTextInput, Animated, - Dimensions, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useNavigation } from "@react-navigation/native"; @@ -19,10 +19,9 @@ import { loginAdmin } from "../../api/api_admin"; import AlertModal from "../../components/ui/AlertModal"; import { useAlert } from "../../hooks/useAlert"; -const { width } = Dimensions.get("window"); - export default function AdminLoginScreen() { const { colors } = useTheme(); + const { width: screenWidth } = useWindowDimensions(); const ACCENT = colors.accent; const [username, setUsername] = useState(""); @@ -41,36 +40,36 @@ export default function AdminLoginScreen() { accentBar: { height: 4, width: "100%" }, heroSection: { alignItems: "center", - paddingTop: 60, - paddingBottom: spacing.xl, + paddingTop: screenWidth < 380 ? 36 : 60, + paddingBottom: spacing.l, }, heroBg: { - width: 120, - height: 120, - borderRadius: 60, + width: screenWidth < 380 ? 96 : 120, + height: screenWidth < 380 ? 96 : 120, + borderRadius: screenWidth < 380 ? 48 : 60, justifyContent: "center", alignItems: "center", }, heroInner: { - width: 88, - height: 88, - borderRadius: 44, + width: screenWidth < 380 ? 68 : 88, + height: screenWidth < 380 ? 68 : 88, + borderRadius: screenWidth < 380 ? 34 : 44, justifyContent: "center", alignItems: "center", }, heroTitle: { - fontSize: fontSize.xxl, + fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "800", color: colors.textWhite, - marginTop: spacing.l, + marginTop: spacing.m, letterSpacing: 0.5, }, heroSubtitle: { - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textMuted, marginTop: spacing.xs, }, - formSection: { paddingHorizontal: spacing.xl, flex: 1 }, + formSection: { paddingHorizontal: screenWidth < 380 ? spacing.l : spacing.xl, flex: 1 }, inputContainer: { flexDirection: "row", alignItems: "center", @@ -121,7 +120,7 @@ export default function AdminLoginScreen() { marginLeft: spacing.xs, }, }), - [colors], + [colors, screenWidth], ); const handleLogin = async () => { diff --git a/frontend-admin/src/screens/auth/CabineLoginScreen.tsx b/frontend-admin/src/screens/auth/CabineLoginScreen.tsx index 2dba90e4..dc817225 100644 --- a/frontend-admin/src/screens/auth/CabineLoginScreen.tsx +++ b/frontend-admin/src/screens/auth/CabineLoginScreen.tsx @@ -8,7 +8,7 @@ import { TouchableOpacity, TextInput as RNTextInput, Animated, - Dimensions, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useNavigation } from "@react-navigation/native"; @@ -19,10 +19,9 @@ import { loginAdmin } from "../../api/api_admin"; import AlertModal from "../../components/ui/AlertModal"; import { useAlert } from "../../hooks/useAlert"; -const { width } = Dimensions.get("window"); - export default function CabineLoginScreen() { const { colors } = useTheme(); + const { width: screenWidth } = useWindowDimensions(); const ACCENT = colors.info; const [username, setUsername] = useState(""); @@ -41,36 +40,36 @@ export default function CabineLoginScreen() { accentBar: { height: 4, width: "100%" }, heroSection: { alignItems: "center", - paddingTop: 60, - paddingBottom: spacing.xl, + paddingTop: screenWidth < 380 ? 36 : 60, + paddingBottom: spacing.l, }, heroBg: { - width: 120, - height: 120, - borderRadius: 60, + width: screenWidth < 380 ? 96 : 120, + height: screenWidth < 380 ? 96 : 120, + borderRadius: screenWidth < 380 ? 48 : 60, justifyContent: "center", alignItems: "center", }, heroInner: { - width: 88, - height: 88, - borderRadius: 44, + width: screenWidth < 380 ? 68 : 88, + height: screenWidth < 380 ? 68 : 88, + borderRadius: screenWidth < 380 ? 34 : 44, justifyContent: "center", alignItems: "center", }, heroTitle: { - fontSize: fontSize.xxl, + fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "800", color: colors.textWhite, - marginTop: spacing.l, + marginTop: spacing.m, letterSpacing: 0.5, }, heroSubtitle: { - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textMuted, marginTop: spacing.xs, }, - formSection: { paddingHorizontal: spacing.xl, flex: 1 }, + formSection: { paddingHorizontal: screenWidth < 380 ? spacing.l : spacing.xl, flex: 1 }, inputContainer: { flexDirection: "row", alignItems: "center", @@ -121,7 +120,7 @@ export default function CabineLoginScreen() { marginLeft: spacing.xs, }, }), - [colors], + [colors, screenWidth], ); const handleLogin = async () => { diff --git a/frontend-admin/src/screens/auth/DeliveryLoginScreen.tsx b/frontend-admin/src/screens/auth/DeliveryLoginScreen.tsx index bec576c1..4f25bc9f 100644 --- a/frontend-admin/src/screens/auth/DeliveryLoginScreen.tsx +++ b/frontend-admin/src/screens/auth/DeliveryLoginScreen.tsx @@ -8,7 +8,7 @@ import { TouchableOpacity, TextInput as RNTextInput, Animated, - Dimensions, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useNavigation } from "@react-navigation/native"; @@ -19,10 +19,9 @@ import { loginAdmin } from "../../api/api_admin"; import AlertModal from "../../components/ui/AlertModal"; import { useAlert } from "../../hooks/useAlert"; -const { width } = Dimensions.get("window"); - export default function DeliveryLoginScreen() { const { colors } = useTheme(); + const { width: screenWidth } = useWindowDimensions(); const ACCENT = colors.success; const [username, setUsername] = useState(""); @@ -41,36 +40,36 @@ export default function DeliveryLoginScreen() { accentBar: { height: 4, width: "100%" }, heroSection: { alignItems: "center", - paddingTop: 60, - paddingBottom: spacing.xl, + paddingTop: screenWidth < 380 ? 36 : 60, + paddingBottom: spacing.l, }, heroBg: { - width: 120, - height: 120, - borderRadius: 60, + width: screenWidth < 380 ? 96 : 120, + height: screenWidth < 380 ? 96 : 120, + borderRadius: screenWidth < 380 ? 48 : 60, justifyContent: "center", alignItems: "center", }, heroInner: { - width: 88, - height: 88, - borderRadius: 44, + width: screenWidth < 380 ? 68 : 88, + height: screenWidth < 380 ? 68 : 88, + borderRadius: screenWidth < 380 ? 34 : 44, justifyContent: "center", alignItems: "center", }, heroTitle: { - fontSize: fontSize.xxl, + fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "800", color: colors.textWhite, - marginTop: spacing.l, + marginTop: spacing.m, letterSpacing: 0.5, }, heroSubtitle: { - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textMuted, marginTop: spacing.xs, }, - formSection: { paddingHorizontal: spacing.xl, flex: 1 }, + formSection: { paddingHorizontal: screenWidth < 380 ? spacing.l : spacing.xl, flex: 1 }, inputContainer: { flexDirection: "row", alignItems: "center", @@ -121,7 +120,7 @@ export default function DeliveryLoginScreen() { marginLeft: spacing.xs, }, }), - [colors], + [colors, screenWidth], ); const handleLogin = async () => { diff --git a/frontend-admin/src/screens/cabine/DashboardScreen.tsx b/frontend-admin/src/screens/cabine/DashboardScreen.tsx index b3aec1d8..62b439fc 100644 --- a/frontend-admin/src/screens/cabine/DashboardScreen.tsx +++ b/frontend-admin/src/screens/cabine/DashboardScreen.tsx @@ -8,6 +8,7 @@ import { TouchableOpacity, Linking, Alert, + useWindowDimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize, borderRadius } from "../../theme"; @@ -26,6 +27,7 @@ import LoadingSpinner from "../../components/ui/LoadingSpinner"; export default function DashboardScreen() { const { colors } = useTheme(); const { username } = useAuth(); + const { width: screenWidth } = useWindowDimensions(); const [tgLinked, setTgLinked] = useState(false); const [tgEnabled, setTgEnabled] = useState(false); @@ -133,54 +135,54 @@ export default function DashboardScreen() { container: { flex: 1, backgroundColor: colors.bgPrimary, - padding: spacing.l, + padding: screenWidth < 380 ? spacing.m : spacing.l, }, welcome: { - fontSize: fontSize.xl, + fontSize: screenWidth < 380 ? fontSize.lg : fontSize.xl, fontWeight: "bold", color: colors.textWhite, marginBottom: spacing.xs, }, subtitle: { - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, color: colors.textSecondary, - marginBottom: spacing.xl, + marginBottom: spacing.l, }, grid: { flexDirection: "row", flexWrap: "wrap", - gap: spacing.m, + gap: screenWidth < 380 ? spacing.s : spacing.m, }, card: { - width: "47%", + width: screenWidth < 360 ? "100%" : "47%", backgroundColor: colors.bgCard, borderRadius: borderRadius.md, - padding: spacing.l, + padding: screenWidth < 380 ? spacing.m : spacing.l, borderWidth: 1, borderColor: colors.borderLight, alignItems: "center", }, iconCircle: { - width: 48, - height: 48, - borderRadius: 24, + width: screenWidth < 380 ? 40 : 48, + height: screenWidth < 380 ? 40 : 48, + borderRadius: screenWidth < 380 ? 20 : 24, justifyContent: "center", alignItems: "center", marginBottom: spacing.s, }, cardValue: { - fontSize: fontSize.xxl, + fontSize: screenWidth < 380 ? fontSize.xl : fontSize.xxl, fontWeight: "bold", color: colors.textWhite, }, cardLabel: { - fontSize: fontSize.sm, + fontSize: screenWidth < 380 ? fontSize.xs : fontSize.sm, color: colors.textSecondary, marginTop: spacing.xs, textAlign: "center", }, }), - [colors], + [colors, screenWidth], ); if (loading) return ; diff --git a/frontend-admin/src/screens/delivery/DashboardScreen.tsx b/frontend-admin/src/screens/delivery/DashboardScreen.tsx index 3a7c3ae8..62c716af 100644 --- a/frontend-admin/src/screens/delivery/DashboardScreen.tsx +++ b/frontend-admin/src/screens/delivery/DashboardScreen.tsx @@ -14,12 +14,12 @@ import { RefreshControl, TouchableOpacity, AppState, - Dimensions, Linking, Modal, StatusBar, ScrollView, TextInput, + useWindowDimensions, } from "react-native"; import Geolocation from "@react-native-community/geolocation"; import { Ionicons } from "@expo/vector-icons"; @@ -55,8 +55,6 @@ import TomTomMap, { } from "../../components/TomTomMap"; import DetailsModal from "../../components/ui/Modal"; -const { width: SCREEN_WIDTH } = Dimensions.get("window"); -const MAP_HEIGHT = 260; const LOCATION_INTERVAL_MS = 15000; const STATUS_LABELS: Record = { @@ -79,6 +77,8 @@ interface EnrichedDelivery extends DeliveryItem { export default function DashboardScreen() { const { colors } = useTheme(); + const { width: screenWidth, height: screenHeight } = useWindowDimensions(); + const MAP_HEIGHT = screenHeight < 700 ? 180 : screenWidth < 380 ? 200 : 260; const [status, setStatus] = useState(null); const [deliveries, setDeliveries] = useState([]); const [queue, setQueue] = useState(null); @@ -1067,17 +1067,19 @@ export default function DashboardScreen() { gap: spacing.m, }, instructionIconBox: { - width: 42, - height: 42, - borderRadius: 12, + width: screenWidth < 380 ? 34 : 42, + height: screenWidth < 380 ? 34 : 42, + borderRadius: 10, backgroundColor: colors.accent, justifyContent: "center", alignItems: "center", + flexShrink: 0, }, instructionText: { color: colors.textWhite, - fontSize: fontSize.md, + fontSize: screenWidth < 380 ? fontSize.sm : fontSize.md, fontWeight: "600", + flex: 1, }, instructionStreet: { color: colors.textMuted, @@ -1259,7 +1261,7 @@ export default function DashboardScreen() { address: { flex: 1, color: colors.textSecondary, - fontSize: fontSize.sm, + fontSize: screenWidth < 380 ? fontSize.xs : fontSize.sm, }, itemsSection: { @@ -1285,10 +1287,12 @@ export default function DashboardScreen() { paddingVertical: spacing.xs, borderBottomWidth: 1, borderBottomColor: colors.borderSubtle, + flexWrap: "nowrap", }, itemName: { + flex: 1, color: colors.textWhite, - fontSize: fontSize.sm, + fontSize: screenWidth < 380 ? fontSize.xs : fontSize.sm, fontWeight: "600", }, itemQty: { @@ -1547,7 +1551,7 @@ export default function DashboardScreen() { fontSize: fontSize.md, }, }), - [colors], + [colors, screenWidth, screenHeight, MAP_HEIGHT], ); if (loading) return ;