+
{direction === "buy" ? (
- {t("detailsStep.summaryBuy", { sats: "", eur: "" }).split("{sats}")[0].trim()}{" "}
-
-
-
- {", "}
- {t("detailsStep.summaryBuy", { sats: "", eur: "" })
- .split("{sats}")[1]
- ?.split("{eur}")[0]
- ?.trim()}{" "}
- {formatEur(eurAmount)}
+ {t("detailsStep.summaryBuy", {
+ eur: formatEur(eurAmount),
+ sats: "",
+ })
+ .replace("{eur}", formatEur(eurAmount))
+ .split("{sats}")
+ .map((part, i) => (
+
+ {part}
+ {i === 0 && (
+
+
+
+ )}
+
+ ))}
) : (
- {t("detailsStep.summarySell", { sats: "", eur: "" })
- .split("{sats}")[0]
- ?.split("{eur}")[0]
- ?.trim()}{" "}
- {formatEur(eurAmount)}
- {", "}
- {t("detailsStep.summarySell", { sats: "", eur: "" })
- .split("{sats}")[0]
- ?.split("{eur}")[1]
- ?.trim()}{" "}
-
-
-
- {t("detailsStep.summarySell", { sats: "", eur: "" }).split("{sats}")[1]?.trim()}
+ {t("detailsStep.summarySell", {
+ sats: "",
+ eur: formatEur(eurAmount),
+ })
+ .split("{sats}")
+ .map((part, i) => (
+
+ {i === 0 && (
+
+
+
+ )}
+ {part.replace("{eur}", formatEur(eurAmount))}
+
+ ))}
)}
diff --git a/frontend/app/styles/shared.ts b/frontend/app/styles/shared.ts
index 6ad0ccc..194b512 100644
--- a/frontend/app/styles/shared.ts
+++ b/frontend/app/styles/shared.ts
@@ -439,6 +439,30 @@ export const formStyles: StyleRecord = {
fontSize: "0.75rem",
color: "#fca5a5",
},
+ error: {
+ fontFamily: tokens.fontSans,
+ fontSize: "0.75rem",
+ color: "#fca5a5",
+ marginTop: "0.25rem",
+ },
+ section: {
+ marginBottom: "2rem",
+ },
+ sectionTitle: {
+ fontFamily: tokens.fontSans,
+ fontSize: "1rem",
+ fontWeight: 600,
+ color: tokens.textSecondary,
+ marginBottom: "1.25rem",
+ marginTop: 0,
+ },
+ actions: {
+ display: "flex",
+ justifyContent: "flex-end",
+ marginTop: "2rem",
+ paddingTop: "1.5rem",
+ borderTop: `1px solid ${tokens.surfaceBorder}`,
+ },
charCount: {
fontFamily: tokens.fontSans,
fontSize: "0.75rem",
@@ -511,6 +535,26 @@ export const buttonStyles: StyleRecord = {
cursor: "not-allowed",
boxShadow: "none",
},
+ /** Primary button alias (for backwards compatibility) */
+ primary: {
+ fontFamily: tokens.fontSans,
+ padding: "1rem",
+ fontSize: "1rem",
+ fontWeight: 600,
+ background: tokens.primaryGradient,
+ color: tokens.white,
+ border: "none",
+ borderRadius: tokens.radiusLg,
+ cursor: "pointer",
+ transition: "transform 0.2s, box-shadow 0.2s",
+ boxShadow: tokens.buttonShadow,
+ },
+ /** Disabled button alias (for backwards compatibility) */
+ disabled: {
+ opacity: 0.5,
+ cursor: "not-allowed",
+ boxShadow: "none",
+ },
};
// =============================================================================
@@ -575,6 +619,17 @@ export const bannerStyles: StyleRecord = {
color: "#4ade80",
marginBottom: "1rem",
},
+ /** Success banner alias (for backwards compatibility) */
+ success: {
+ fontFamily: tokens.fontSans,
+ fontSize: "0.875rem",
+ padding: "1rem",
+ background: "rgba(34, 197, 94, 0.15)",
+ border: `1px solid ${tokens.successBorder}`,
+ borderRadius: tokens.radiusMd,
+ color: "#4ade80",
+ marginBottom: "1rem",
+ },
};
// =============================================================================
diff --git a/frontend/e2e/exchange.spec.ts b/frontend/e2e/exchange.spec.ts
index 26cafda..5ead442 100644
--- a/frontend/e2e/exchange.spec.ts
+++ b/frontend/e2e/exchange.spec.ts
@@ -148,6 +148,44 @@ test.describe("Exchange Page - Regular User Access", () => {
timeout: 10000,
});
});
+
+ test("summary card displays correct text for buy and sell directions", async ({ page }) => {
+ await page.goto("/exchange");
+ await expect(page.getByRole("heading", { name: "Exchange Bitcoin" })).toBeVisible();
+
+ // Wait for price data to load
+ await expect(page.getByText("Market:")).toBeVisible({ timeout: 5000 });
+
+ // Test BUY direction summary
+ const buyButton = page.getByRole("button", { name: "Buy BTC" });
+ await buyButton.click();
+
+ // Wait for summary to update
+ await page.waitForTimeout(1000);
+
+ // Check that summary contains "You pay" and "you receive" with EUR amount and sats
+ const summaryElement = page.getByTestId("trade-summary");
+ await expect(summaryElement).toBeVisible({ timeout: 5000 });
+ const summaryText = await summaryElement.textContent();
+ expect(summaryText).toContain("You pay");
+ expect(summaryText).toContain("you receive");
+ expect(summaryText).toMatch(/€\s*\d+/); // Should contain EUR amount
+ expect(summaryText).toMatch(/\d+\s*sats/); // Should contain sats amount
+
+ // Test SELL direction summary
+ const sellButton = page.getByRole("button", { name: "Sell BTC" });
+ await sellButton.click();
+
+ // Wait for summary to update
+ await page.waitForTimeout(1000);
+
+ // Check that summary contains "You pay" and "you receive" with sats and EUR amount
+ const summaryTextSell = await summaryElement.textContent();
+ expect(summaryTextSell).toContain("You pay");
+ expect(summaryTextSell).toContain("you receive");
+ expect(summaryTextSell).toMatch(/€\s*\d+/); // Should contain EUR amount
+ expect(summaryTextSell).toMatch(/\d+\s*sats/); // Should contain sats amount
+ });
});
test.describe("Exchange Page - With Availability", () => {
diff --git a/frontend/locales/ca/admin.json b/frontend/locales/ca/admin.json
index 69a9f1f..136f186 100644
--- a/frontend/locales/ca/admin.json
+++ b/frontend/locales/ca/admin.json
@@ -114,12 +114,12 @@
"title": "Configuració de Preus",
"subtitle": "Configura els preus de prima i els límits d'import de les operacions",
"premiumSettings": "Configuració de Prima",
- "premiumBuy": "Prima per COMPRAR",
- "premiumSell": "Prima per VENDRE",
+ "premiumBuy": "Prima quan l'Usuari Compra BTC (Usuari paga EUR, rep BTC)",
+ "premiumSell": "Prima quan l'Usuari Vén BTC (Usuari paga BTC, rep EUR)",
"smallTradeThreshold": "Umbral d'Operacions Petites",
"smallTradeExtraPremium": "Prima Extra per Operacions Petites",
- "tradeLimitsBuy": "Límits d'Import d'Operacions (COMPRAR)",
- "tradeLimitsSell": "Límits d'Import d'Operacions (VENDRE)",
+ "tradeLimitsBuy": "Límits d'Import en Comprar BTC (EUR pagat per l'usuari)",
+ "tradeLimitsSell": "Límits d'Import en Vendre BTC (EUR rebut per l'usuari)",
"minAmount": "Import Mínim",
"maxAmount": "Import Màxim",
"save": "Guardar Canvis",
diff --git a/frontend/locales/ca/exchange.json b/frontend/locales/ca/exchange.json
index 01d275d..c4c69bf 100644
--- a/frontend/locales/ca/exchange.json
+++ b/frontend/locales/ca/exchange.json
@@ -31,8 +31,8 @@
"required": "*",
"lightningThreshold": "Els pagaments Lightning només estan disponibles per importants fins a €{max}",
"amount": "Quantitat (EUR)",
- "summaryBuy": "Compres {sats}, vens {eur}",
- "summarySell": "Compres {eur}, vens {sats}",
+ "summaryBuy": "Pagues {eur}, reps {sats}",
+ "summarySell": "Pagues {sats}, reps {eur}",
"continueToBooking": "Continuar a reserva"
},
"bookingStep": {
diff --git a/frontend/locales/en/admin.json b/frontend/locales/en/admin.json
index 548dc2e..3386345 100644
--- a/frontend/locales/en/admin.json
+++ b/frontend/locales/en/admin.json
@@ -114,12 +114,12 @@
"title": "Pricing Configuration",
"subtitle": "Configure premium pricing and trade amount limits",
"premiumSettings": "Premium Settings",
- "premiumBuy": "Premium for BUY",
- "premiumSell": "Premium for SELL",
+ "premiumBuy": "Premium when User Buys BTC (User pays EUR, receives BTC)",
+ "premiumSell": "Premium when User Sells BTC (User pays BTC, receives EUR)",
"smallTradeThreshold": "Small Trade Threshold",
"smallTradeExtraPremium": "Extra Premium for Small Trades",
- "tradeLimitsBuy": "Trade Amount Limits (BUY)",
- "tradeLimitsSell": "Trade Amount Limits (SELL)",
+ "tradeLimitsBuy": "Trade Amount Limits when Buying BTC (EUR paid by user)",
+ "tradeLimitsSell": "Trade Amount Limits when Selling BTC (EUR received by user)",
"minAmount": "Minimum Amount",
"maxAmount": "Maximum Amount",
"save": "Save Changes",
diff --git a/frontend/locales/en/exchange.json b/frontend/locales/en/exchange.json
index 7e1d4ee..ff34f18 100644
--- a/frontend/locales/en/exchange.json
+++ b/frontend/locales/en/exchange.json
@@ -31,8 +31,8 @@
"required": "*",
"lightningThreshold": "Lightning payments are only available for amounts up to €{max}",
"amount": "Amount (EUR)",
- "summaryBuy": "You buy {sats}, you sell {eur}",
- "summarySell": "You buy {eur}, you sell {sats}",
+ "summaryBuy": "You pay {eur}, you receive {sats}",
+ "summarySell": "You pay {sats}, you receive {eur}",
"continueToBooking": "Continue to Booking"
},
"bookingStep": {
diff --git a/frontend/locales/es/admin.json b/frontend/locales/es/admin.json
index d82431d..9c2cf8d 100644
--- a/frontend/locales/es/admin.json
+++ b/frontend/locales/es/admin.json
@@ -114,12 +114,12 @@
"title": "Configuración de Precios",
"subtitle": "Configura los precios de prima y los límites de importe de las operaciones",
"premiumSettings": "Configuración de Prima",
- "premiumBuy": "Prima para COMPRAR",
- "premiumSell": "Prima para VENDER",
+ "premiumBuy": "Prima cuando el Usuario Compra BTC (Usuario paga EUR, recibe BTC)",
+ "premiumSell": "Prima cuando el Usuario Vende BTC (Usuario paga BTC, recibe EUR)",
"smallTradeThreshold": "Umbral de Operaciones Pequeñas",
"smallTradeExtraPremium": "Prima Extra para Operaciones Pequeñas",
- "tradeLimitsBuy": "Límites de Importe de Operaciones (COMPRAR)",
- "tradeLimitsSell": "Límites de Importe de Operaciones (VENDER)",
+ "tradeLimitsBuy": "Límites de Importe al Comprar BTC (EUR pagado por el usuario)",
+ "tradeLimitsSell": "Límites de Importe al Vender BTC (EUR recibido por el usuario)",
"minAmount": "Importe Mínimo",
"maxAmount": "Importe Máximo",
"save": "Guardar Cambios",
diff --git a/frontend/locales/es/exchange.json b/frontend/locales/es/exchange.json
index ee5ad5e..0a171fb 100644
--- a/frontend/locales/es/exchange.json
+++ b/frontend/locales/es/exchange.json
@@ -31,8 +31,8 @@
"required": "*",
"lightningThreshold": "Los pagos Lightning solo están disponibles para montos de hasta €{max}",
"amount": "Cantidad (EUR)",
- "summaryBuy": "Compras {sats}, vendes {eur}",
- "summarySell": "Compras {eur}, vendes {sats}",
+ "summaryBuy": "Pagas {eur}, recibes {sats}",
+ "summarySell": "Pagas {sats}, recibes {eur}",
"continueToBooking": "Continuar a reserva"
},
"bookingStep": {
diff --git a/shared/constants.json b/shared/constants.json
index e930667..4d5e7b6 100644
--- a/shared/constants.json
+++ b/shared/constants.json
@@ -27,7 +27,7 @@
"slotDurationMinutes": 15,
"maxAdvanceDays": 30,
"minAdvanceDays": 1,
- "eurTradeIncrement": 20,
+ "eurTradeIncrement": 5,
"priceRefreshSeconds": 60,
"priceStalenessSeconds": 300,
"lightningMaxEur": 1000