import { selectStrategy } from "../services/api/strategyApi";
-/**
- * StrategyScreen
- * --------------
- * Maintenant :
- * - On garde la liste locale (fetchStrategies)
- * - On sync vers serveur : POST /api/strategy/select
- * - On met à jour le settings local pour affichage immédiat
- */
export default function StrategyScreen() {
const [settings, setSettings] = useState<UserSettings | null>(null);
const [strategies, setStrategies] = useState<StrategyOption[]>([]);
setLoading(true);
const [s, list] = await Promise.all([loadSettings(), fetchStrategies()]);
if (!active) return;
-
setSettings(s);
setStrategies(list);
} finally {
}
init();
-
return () => {
active = false;
};
const isSelected = (key: StrategyKey) => settings.selectedStrategyKey === key;
const handleSelect = async (key: StrategyKey) => {
+ const prev = settings.selectedStrategyKey;
+
try {
setBusy(true);
setInfo(null);
- // 1) Update local immédiat (UX + dashboard)
+ // Pair alignée dashboard : BTC + devise settings
+ const currency = settings.currency === "USD" ? "USD" : "EUR";
+ const pair = `BTC/${currency}`;
+
+ // 1) Serveur d’abord (align Stéphane)
+ await selectStrategy({ pair, mode: key, params: {} });
+
+ // 2) Puis local (affichage immédiat)
const next: UserSettings = { ...settings, selectedStrategyKey: key };
await saveSettings(next);
setSettings(next);
- // 2) Sync serveur (contrat Stéphane)
- // Pair cible : pour l’instant BTC/EUR (comme le dashboard). Si vous passez multi-crypto, on l’adaptera.
- await selectStrategy({
- pair: "BTC/EUR",
- mode: key,
- params: {}, // si un jour tu as des paramètres, tu les mets ici
- });
-
- setInfo(`Stratégie sélectionnée : ${key} ✅ (sync serveur OK)`);
+ setInfo(`Stratégie sélectionnée : ${key} ✅`);
} catch (e: any) {
+ // rollback local si besoin
+ const rollback: UserSettings = { ...settings, selectedStrategyKey: prev };
+ await saveSettings(rollback);
+ setSettings(rollback);
+
setInfo(`Erreur serveur stratégie : ${e?.message ?? "inconnue"}`);
} finally {
setBusy(false);
ListHeaderComponent={
<View style={ui.card}>
<Text style={ui.title}>Stratégie</Text>
- <Text style={ui.muted}>
- Choisis une stratégie. Elle sera affichée sur le Dashboard.
- </Text>
+ <Text style={ui.muted}>Choisis une stratégie. Elle est enregistrée sur le serveur.</Text>
<Text style={[ui.muted, { marginTop: 8 }]}>
Actuelle : <Text style={styles.boldInline}>{settings.selectedStrategyKey}</Text>
}
const styles = StyleSheet.create({
- safeArea: {
- flex: 1,
- backgroundColor: ui.screen.backgroundColor,
- },
-
- boldInline: {
- fontWeight: "900",
- color: "#0f172a",
- },
-
- fullButton: {
- flexGrow: 0,
- flexBasis: "auto",
- width: "100%",
- marginTop: 12,
- },
-
- cardSelected: {
- borderColor: "#16a34a",
- },
-
- btnSelected: {
- opacity: 0.9,
- },
-
- btnDisabled: {
- opacity: 0.6,
- },
-
- riskTag: {
- fontWeight: "900",
- opacity: 0.75,
- },
+ safeArea: { flex: 1, backgroundColor: ui.screen.backgroundColor },
+ boldInline: { fontWeight: "900", color: "#0f172a" },
+ fullButton: { flexGrow: 0, flexBasis: "auto", width: "100%", marginTop: 12 },
+ cardSelected: { borderColor: "#16a34a" },
+ btnSelected: { opacity: 0.9 },
+ btnDisabled: { opacity: 0.6 },
+ riskTag: { fontWeight: "900", opacity: 0.75 },
});
\ No newline at end of file
import type { StrategyKey } from "../../types/Strategy";
/**
- * strategyApi (API)
- * -----------------
- * Contrat (objectif) :
+ * strategyApi — aligné strategy-service (Stéphane)
* POST /api/strategy/select
- * Body:
- * {
- * userId: string,
- * pair: "BTC/EUR",
- * mode: "RSI_SIMPLE" | "MA_CROSS" | ...,
- * params: object
- * }
+ * body: { userId, pairId, mode, params }
*
- * Réponse possible :
- * - { ok:true, data:{ ... } } (géré par http.ts)
- * - ou une réponse vide -> on considère que c'est OK si pas d'erreur HTTP
+ * IMPORTANT:
+ * - pairId est obligatoire côté serveur.
+ * - params est mieux en JSON string (stocké DB).
*/
+
+function pairToPairId(pair: string): number {
+ // Convention du projet : (MarketDataRepo mentionne pairId=1 pour BTC)
+ const p = pair.trim().toUpperCase();
+ if (p.startsWith("BTC/")) return 1;
+ if (p.startsWith("ETH/")) return 2;
+ if (p.startsWith("LTC/")) return 3;
+ throw new Error(`Pair non supportée (pas de pairId) : ${pair}`);
+}
+
export async function selectStrategy(params: {
- pair: string; // ex: "BTC/EUR"
- mode: StrategyKey; // ex: "RSI_SIMPLE"
+ pair: string; // ex: "BTC/EUR"
+ mode: StrategyKey; // ex: "RSI_SIMPLE"
params?: Record<string, unknown>;
}): Promise<void> {
const session = await loadSession();
const userId = session?.userId;
if (!userId) throw new Error("Session absente : impossible de sélectionner une stratégie.");
+ const pair = params.pair.trim().toUpperCase();
+ const pairId = pairToPairId(pair);
+
await apiPost(`/strategy/select`, {
userId,
- pair: params.pair,
+ pairId, // ✅ requis serveur
mode: params.mode,
- params: params.params ?? {},
+ params: JSON.stringify(params.params ?? {}), // ✅ stockable DB
});
}
\ No newline at end of file