]> git.digitality.be Git - pdw25-26/commitdiff
Module : Refractor dashboardScreen (réajout box alert)
authorThibaud Moustier <thibaudmoustier0@gmail.com>
Sat, 28 Feb 2026 20:25:54 +0000 (21:25 +0100)
committerThibaud Moustier <thibaudmoustier0@gmail.com>
Sat, 28 Feb 2026 20:25:54 +0000 (21:25 +0100)
Wallette/mobile/src/screens/DashboardScreen.tsx

index b0aab8d95fbbe622d6e158c17347aa7155bbf4e2..8834cfd6a0733548dbe064b43e86dc7404349a37 100644 (file)
@@ -43,9 +43,11 @@ const CRYPTOS: CryptoSymbol[] = ["BTC", "ETH", "LTC"];
 function walletAddressKey(userId: string) {
   return `walletAddress:${userId}`;
 }
+
 function normalizeSymbol(s: string) {
   return s.trim().toUpperCase();
 }
+
 function mergePortfolios(base: PortfolioState, patch: PortfolioState): PortfolioState {
   const map = new Map<string, number>();
   for (const a of base.assets) map.set(normalizeSymbol(a.symbol), a.quantity);
@@ -67,7 +69,10 @@ export default function DashboardScreen() {
 
   const [userId, setUserId] = useState<string | null>(null);
   const [settings, setSettings] = useState<UserSettings | null>(null);
-  const [portfolio, setPortfolio] = useState<PortfolioState>({ assets: [], updatedAtMs: Date.now() });
+  const [portfolio, setPortfolio] = useState<PortfolioState>({
+    assets: [],
+    updatedAtMs: Date.now(),
+  });
 
   const [selectedCrypto, setSelectedCrypto] = useState<CryptoSymbol>("BTC");
 
@@ -95,10 +100,13 @@ export default function DashboardScreen() {
 
   const urgentAlert = useMemo(() => {
     if (liveAlerts.length === 0) return null;
+
     const critical = liveAlerts.find((a) => String(a.alertLevel).toUpperCase() === "CRITICAL");
     if (critical) return critical;
+
     const warning = liveAlerts.find((a) => String(a.alertLevel).toUpperCase() === "WARNING");
     if (warning) return warning;
+
     return liveAlerts[0];
   }, [liveAlerts]);
 
@@ -122,6 +130,7 @@ export default function DashboardScreen() {
       setWalletAddress("");
     }
 
+    // Dashboard summary (prix+signal)
     try {
       const dash = await getDashboardSummary();
       setSummary(dash);
@@ -130,6 +139,7 @@ export default function DashboardScreen() {
       setSoftError(`Signal/Prix indisponibles (API). DEV=${ENV_MODE}. Base REST: ${API_BASE_URL}`);
     }
 
+    // Wallet API (si dispo) -> fusion
     if (uid) {
       try {
         const apiPortfolio = await getPortfolioFromApi();
@@ -141,6 +151,7 @@ export default function DashboardScreen() {
       }
     }
 
+    // Alertes REST (liste)
     if (uid) {
       try {
         const history = await getAlertHistory(10);
@@ -163,13 +174,14 @@ export default function DashboardScreen() {
           if (alive) setLoading(false);
         }
       })();
+
       return () => {
         alive = false;
       };
     }, [refreshAll])
   );
 
-  // ✅ FIX string|null : on connecte socket seulement si uid existe
+  // Socket live (✅ connect seulement si userId existe)
   useEffect(() => {
     let unsub: null | (() => void) = null;
     let alive = true;
@@ -303,15 +315,19 @@ export default function DashboardScreen() {
           </View>
         )}
 
+        {/* Compte */}
         <View style={ui.card}>
           <Text style={ui.title}>Compte utilisateur</Text>
           <View style={ui.rowBetween}>
-            <Text style={ui.muted}>UserId : <Text style={styles.bold}>{userId ?? "—"}</Text></Text>
+            <Text style={ui.muted}>
+              UserId : <Text style={styles.bold}>{userId ?? "—"}</Text>
+            </Text>
             <Text style={ui.muted}>Socket : {socketConnected ? "ON ✅" : "OFF ⚠️"}</Text>
           </View>
           {!!socketInfo && <Text style={[ui.muted, { marginTop: 6 }]}>{socketInfo}</Text>}
         </View>
 
+        {/* Crypto + adresse */}
         <View style={ui.card}>
           <Text style={ui.title}>Choisir une cryptomonnaie</Text>
 
@@ -350,39 +366,78 @@ export default function DashboardScreen() {
           {!!walletAddressInfo && <Text style={[ui.muted, { marginTop: 8 }]}>{walletAddressInfo}</Text>}
         </View>
 
+        {/* Solde */}
+        <View style={ui.card}>
+          <Text style={ui.title}>Solde</Text>
+          <Text style={styles.bigValue}>
+            {selectedQty.toFixed(6)} {selectedCrypto}
+          </Text>
+          <Text style={ui.muted}>Portefeuille local (+ sync serveur si dispo)</Text>
+        </View>
+
+        {/* Prix */}
         <View style={ui.card}>
           <Text style={ui.title}>Prix</Text>
           <Text style={ui.muted}>{pair}</Text>
-          <Text style={styles.bigValue}>{(summary?.price ?? 0).toFixed(2)} {currency}</Text>
+          <Text style={styles.bigValue}>
+            {(summary?.price ?? 0).toFixed(2)} {currency}
+          </Text>
+
           <TouchableOpacity style={[ui.button, { marginTop: 10 }]} onPress={() => void refreshAll()}>
             <Text style={ui.buttonText}>Actualiser</Text>
           </TouchableOpacity>
         </View>
 
+        {/* Signal */}
         <View style={ui.card}>
           <Text style={ui.title}>Signal du marché</Text>
           {summary ? (
             <>
               <Text style={styles.signalDecision}>{summary.decision}</Text>
-              <Text style={ui.muted}>{summary.alertLevel} — Confiance {Math.round(summary.confidence * 100)}%</Text>
-              <Text style={[ui.muted, { marginTop: 6 }]} numberOfLines={3}>{summary.reason}</Text>
+              <Text style={ui.muted}>
+                {summary.alertLevel} — Confiance {Math.round(summary.confidence * 100)}%
+              </Text>
+              <Text style={[ui.muted, { marginTop: 6 }]} numberOfLines={3}>
+                {summary.reason}
+              </Text>
             </>
           ) : (
             <Text style={ui.muted}>Aucune donnée pour le moment.</Text>
           )}
+        </View>
 
-          {urgentAlert && (
-            <View style={styles.urgentBox}>
-              <Text style={styles.urgentTitle}>
-                {String(urgentAlert.alertLevel ?? "INFO")} — {String(urgentAlert.action ?? "HOLD")}
-              </Text>
-              <Text style={ui.muted} numberOfLines={2}>
-                {urgentAlert.reason ?? urgentAlert.message ?? "—"}
-              </Text>
+        {/* Alertes (bloc dédié) */}
+        <TouchableOpacity activeOpacity={0.85} onPress={() => navigation.navigate("Alerts" as never)}>
+          <View style={ui.card}>
+            <View style={ui.rowBetween}>
+              <Text style={ui.title}>Alertes</Text>
+              <Text style={ui.muted}>Ouvrir</Text>
             </View>
-          )}
-        </View>
 
+            {urgentAlert ? (
+              <>
+                <Text style={[styles.urgentTitle, { marginTop: 10 }]}>
+                  {String(urgentAlert.alertLevel ?? "INFO")} — {String(urgentAlert.action ?? "HOLD")}
+                </Text>
+
+                <Text style={ui.muted} numberOfLines={2}>
+                  {urgentAlert.reason ?? urgentAlert.message ?? "—"}
+                </Text>
+
+                <Text style={ui.muted}>
+                  {urgentAlert.pair ?? ""}{" "}
+                  {typeof urgentAlert.confidence === "number"
+                    ? `— ${Math.round(urgentAlert.confidence * 100)}%`
+                    : ""}
+                </Text>
+              </>
+            ) : (
+              <Text style={[ui.muted, { marginTop: 10 }]}>Aucune alerte pour le moment.</Text>
+            )}
+          </View>
+        </TouchableOpacity>
+
+        {/* Stratégie */}
         <TouchableOpacity activeOpacity={0.85} onPress={() => navigation.navigate("Strategy" as never)}>
           <View style={ui.card}>
             <View style={ui.rowBetween}>
@@ -395,6 +450,7 @@ export default function DashboardScreen() {
           </View>
         </TouchableOpacity>
 
+        {/* Actions */}
         <View style={ui.card}>
           <Text style={ui.title}>Actions</Text>
           <View style={styles.buySellRow}>
@@ -405,8 +461,12 @@ export default function DashboardScreen() {
               <Text style={styles.buySellText}>Vendre</Text>
             </TouchableOpacity>
           </View>
+          <Text style={[ui.muted, { marginTop: 10 }]} numberOfLines={2}>
+            Note : Acheter/Vendre = simulation (registre local). Pas de trading réel.
+          </Text>
         </View>
 
+        {/* Modal BUY/SELL */}
         <Modal visible={tradeOpen} transparent animationType="fade" onRequestClose={() => setTradeOpen(false)}>
           <View style={styles.modalBackdrop}>
             <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : undefined} style={styles.modalWrap}>
@@ -415,7 +475,9 @@ export default function DashboardScreen() {
                   {tradeSide === "BUY" ? "Acheter" : "Vendre"} {selectedCrypto}
                 </Text>
 
-                <Text style={ui.muted}>Prix : {(summary?.price ?? 0).toFixed(2)} {currency}</Text>
+                <Text style={ui.muted}>
+                  Prix : {(summary?.price ?? 0).toFixed(2)} {currency}
+                </Text>
 
                 <Text style={[ui.muted, { marginTop: 12 }]}>Quantité</Text>
                 <TextInput
@@ -451,10 +513,12 @@ export default function DashboardScreen() {
 
 const styles = StyleSheet.create({
   safeArea: { flex: 1, backgroundColor: ui.screen.backgroundColor },
+
   bannerWarn: { borderColor: "#ca8a04" },
   bannerText: { color: "#ca8a04", fontWeight: "900" },
 
   bold: { fontWeight: "900", color: "#0f172a" },
+
   bigValue: { marginTop: 10, fontSize: 22, fontWeight: "900", color: "#0f172a" },
   signalDecision: { marginTop: 10, fontSize: 26, fontWeight: "900", color: "#0f172a" },
 
@@ -494,14 +558,6 @@ const styles = StyleSheet.create({
   },
   secondaryButtonText: { fontWeight: "900", color: "#0f172a", opacity: 0.9 },
 
-  urgentBox: {
-    marginTop: 12,
-    borderWidth: 1,
-    borderColor: "#e5e7eb",
-    borderRadius: 12,
-    padding: 10,
-    backgroundColor: "#fff",
-  },
   urgentTitle: { fontWeight: "900", color: "#0f172a" },
 
   buySellRow: { flexDirection: "row", gap: 10, marginTop: 10 },
@@ -514,6 +570,7 @@ const styles = StyleSheet.create({
   modalCard: { backgroundColor: "#fff", borderRadius: 16, padding: 16, borderWidth: 1, borderColor: "#e5e7eb" },
   modalTitle: { fontSize: 18, fontWeight: "900", color: "#0f172a" },
   modalError: { marginTop: 10, fontWeight: "800", color: "#dc2626" },
+
   modalButtonsRow: { flexDirection: "row", gap: 10, marginTop: 14 },
   modalBtn: { flex: 1, paddingVertical: 12, borderRadius: 12, alignItems: "center" },
   modalBtnSecondary: { backgroundColor: "#fff", borderWidth: 1, borderColor: "#e5e7eb" },