chore: build

This commit is contained in:
2026-06-14 00:20:56 +02:00
parent 83075e30d6
commit be7e3b3bd8
@@ -6,7 +6,6 @@ import {
ScrollView,
RefreshControl,
TouchableOpacity,
useWindowDimensions,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { spacing, fontSize } from "../../theme";
@@ -18,23 +17,13 @@ import LoadingSpinner from "../../components/ui/LoadingSpinner";
import Card from "../../components/ui/Card";
type Period = "day" | "week" | "month";
type Metric = "count" | "revenue";
const BAR_MAX_HEIGHT = 110;
const BAR_WIDTH = 36;
const BAR_GAP = 8;
function BarChart({
data,
metric,
colors,
}: {
data: StatPoint[];
metric: Metric;
colors: any;
}) {
const values = data.map((d) => (metric === "count" ? d.count : d.revenue));
const maxVal = Math.max(...values, 1);
function BarChart({ data, colors }: { data: StatPoint[]; colors: any }) {
const maxVal = Math.max(...data.map((d) => d.count), 1);
if (data.length === 0) {
return (
@@ -51,7 +40,7 @@ function BarChart({
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{ marginTop: spacing.m }}>
<View style={{ flexDirection: "row", alignItems: "flex-end", paddingBottom: spacing.s, paddingHorizontal: 4 }}>
{data.map((point, i) => {
const val = metric === "count" ? point.count : point.revenue;
const val = point.count;
const barH = Math.max(4, (val / maxVal) * BAR_MAX_HEIGHT);
const isLast = i === data.length - 1;
return (
@@ -64,9 +53,7 @@ function BarChart({
}}
>
<Text style={{ color: colors.textMuted, fontSize: 9, marginBottom: 3 }}>
{metric === "count"
? val > 0 ? String(val) : ""
: val > 0 ? (val >= 1000 ? `${(val / 1000).toFixed(1)}k` : `${Math.round(val)}`) : ""}
{val > 0 ? String(val) : ""}
</Text>
<View
style={{
@@ -105,7 +92,6 @@ export default function StatsScreen() {
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [period, setPeriod] = useState<Period>("week");
const [metric, setMetric] = useState<Metric>("count");
const loadData = useCallback(async () => {
try {
@@ -137,18 +123,13 @@ export default function StatsScreen() {
const completed = deliveries.filter((d) => d.status === "livre" || d.status === "approved").length;
const inProgress = deliveries.filter((d) => d.status === "en_route").length;
const pending = deliveries.filter((d) => d.status === "assigned").length;
const totalRevenue = deliveries
.filter((d) => d.status === "livre" || d.status === "approved")
.reduce((s, d) => s + (d.total_prix - (d.referral_used ?? 0)), 0);
const chartData = period === "day" ? byDay : period === "week" ? byWeek : byMonth;
const periodTotal = useMemo(() => {
return chartData.reduce(
(acc, p) => ({ count: acc.count + p.count, revenue: acc.revenue + p.revenue }),
{ count: 0, revenue: 0 },
);
}, [chartData]);
const periodTotal = useMemo(
() => chartData.reduce((acc, p) => acc + p.count, 0),
[chartData],
);
const periodLabels: Record<Period, string> = {
day: "30 derniers jours",
@@ -175,22 +156,6 @@ export default function StatsScreen() {
marginTop: spacing.xs,
textAlign: "center",
},
revenueCard: {
alignItems: "center",
paddingVertical: spacing.l,
marginTop: spacing.m,
},
revenueValue: {
fontSize: 28,
fontWeight: "800",
color: colors.success,
marginTop: spacing.s,
},
revenueLabel: {
color: colors.textMuted,
fontSize: fontSize.sm,
marginTop: spacing.xs,
},
sectionTitle: {
color: colors.textWhite,
fontSize: fontSize.lg,
@@ -222,26 +187,6 @@ export default function StatsScreen() {
color: colors.textMuted,
},
periodBtnTextActive: { color: colors.accent },
metricRow: {
flexDirection: "row",
gap: spacing.s,
marginBottom: spacing.s,
},
metricBtn: {
flex: 1,
paddingVertical: spacing.xs,
borderRadius: 6,
alignItems: "center",
backgroundColor: colors.bgCard,
borderWidth: 1,
borderColor: colors.border,
},
metricBtnActive: {
backgroundColor: colors.success + "22",
borderColor: colors.success,
},
metricBtnText: { fontSize: fontSize.xs, fontWeight: "600", color: colors.textMuted },
metricBtnTextActive: { color: colors.success },
chartCard: { paddingBottom: spacing.s },
summaryRow: {
flexDirection: "row",
@@ -287,15 +232,6 @@ export default function StatsScreen() {
))}
</View>
{/* Revenu total all-time */}
<Card style={styles.revenueCard}>
<Ionicons name="cash-outline" size={28} color={colors.success} />
<Text style={styles.revenueValue}>
{totalRevenue.toLocaleString("fr-FR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</Text>
<Text style={styles.revenueLabel}>Revenu total généré</Text>
</Card>
{/* Section graphiques */}
<Text style={styles.sectionTitle}>Évolution</Text>
@@ -314,44 +250,17 @@ export default function StatsScreen() {
))}
</View>
{/* Sélecteur métrique */}
<View style={styles.metricRow}>
<TouchableOpacity
style={[styles.metricBtn, metric === "count" && styles.metricBtnActive]}
onPress={() => setMetric("count")}
>
<Text style={[styles.metricBtnText, metric === "count" && styles.metricBtnTextActive]}>
Commandes
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.metricBtn, metric === "revenue" && styles.metricBtnActive]}
onPress={() => setMetric("revenue")}
>
<Text style={[styles.metricBtnText, metric === "revenue" && styles.metricBtnTextActive]}>
Revenus ()
</Text>
</TouchableOpacity>
</View>
<Card style={styles.chartCard}>
<Text style={styles.periodHint}>{periodLabels[period]}</Text>
<BarChart data={chartData} metric={metric} colors={colors} />
<BarChart data={chartData} colors={colors} />
{/* Totaux de la période */}
{chartData.length > 0 && (
<View style={styles.summaryRow}>
<View style={styles.summaryItem}>
<Text style={styles.summaryValue}>{periodTotal.count}</Text>
<Text style={styles.summaryValue}>{periodTotal}</Text>
<Text style={styles.summaryLabel}>livraisons</Text>
</View>
<View style={[styles.summaryItem, { borderLeftWidth: 1, borderLeftColor: colors.border }]}>
<Text style={[styles.summaryValue, { color: colors.success }]}>
{periodTotal.revenue.toLocaleString("fr-FR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</Text>
<Text style={styles.summaryLabel}>revenus</Text>
</View>
</View>
)}
</Card>