dev #21

Merged
Seazn merged 35 commits from dev into main 2026-05-21 17:34:44 +00:00
2 changed files with 10 additions and 8 deletions
Showing only changes of commit bc8e3ea5c2 - Show all commits

View File

@ -233,7 +233,7 @@ export default function EditSubscriptionPage() {
/> />
)} )}
<div className="max-w-[1820px] mx-auto px-4 sm:px-6 xl:px-10 py-8 space-y-5"> <div className="max-w-455 mx-auto px-4 sm:px-6 xl:px-10 py-8 space-y-5">
{/* Header card */} {/* Header card */}
<div className="rounded-[28px] border border-white/80 bg-white/90 px-8 py-6 shadow-[0_24px_70px_-40px_rgba(15,23,42,0.3)] backdrop-blur flex flex-wrap items-center justify-between gap-4"> <div className="rounded-[28px] border border-white/80 bg-white/90 px-8 py-6 shadow-[0_24px_70px_-40px_rgba(15,23,42,0.3)] backdrop-blur flex flex-wrap items-center justify-between gap-4">
@ -289,11 +289,11 @@ export default function EditSubscriptionPage() {
</div> </div>
)} )}
{showThumb && ( {showThumb && (
<div className="relative w-full h-full min-h-[340px] flex items-center justify-center bg-slate-100 p-6"> <div className="relative flex h-full min-h-85 w-full items-center justify-center bg-slate-100 p-6">
<img <img
src={previewUrl || existingThumbnail || ''} src={previewUrl || existingThumbnail || ''}
alt={previewUrl ? 'Preview' : item.title} alt={previewUrl ? 'Preview' : item.title}
className="max-h-[320px] max-w-full object-contain rounded-xl shadow-lg" className="max-h-80 max-w-full object-contain rounded-xl shadow-lg"
/> />
<div className="absolute top-4 right-4 flex gap-2"> <div className="absolute top-4 right-4 flex gap-2">
{previewUrl && ( {previewUrl && (
@ -334,11 +334,12 @@ export default function EditSubscriptionPage() {
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2"> <div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
{/* Price */} {/* Price */}
<div> <div>
<label htmlFor="price" className="block text-sm font-semibold text-slate-700 mb-1">Price</label> <label htmlFor="price" className="block text-sm font-semibold text-slate-700 mb-1">Price per pack</label>
<input id="price" type="number" min={0} step={0.01} required <input id="price" type="number" min={0} step={0.01} required
className="block w-full rounded-xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-900 shadow-sm placeholder:text-slate-400 focus:ring-2 focus:ring-slate-900 focus:border-transparent" className="block w-full rounded-xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-900 shadow-sm placeholder:text-slate-400 focus:ring-2 focus:ring-slate-900 focus:border-transparent"
value={price} onChange={e => setPrice(e.target.value)} value={price} onChange={e => setPrice(e.target.value)}
onBlur={e => { const n = parseFloat(e.target.value); if (!isNaN(n)) setPrice(n.toFixed(2)); }} /> onBlur={e => { const n = parseFloat(e.target.value); if (!isNaN(n)) setPrice(n.toFixed(2)); }} />
<p className="mt-1 text-xs text-slate-500">Admin input is handled per pack. The backend continues storing the internal per-capsule value automatically.</p>
</div> </div>
{/* Currency */} {/* Currency */}

View File

@ -1,5 +1,6 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import useAuthStore from '../../../store/authStore'; import useAuthStore from '../../../store/authStore';
import { CAPSULES_PER_PACK } from '../../../coffee-abonnements/lib/orderRules';
export type CoffeeItem = { export type CoffeeItem = {
id: number; id: number;
@ -63,7 +64,7 @@ export default function useCoffeeManagement() {
const text = await res.text(); const text = await res.text();
try { return JSON.parse(text) as T; } catch { return {} as T; } try { return JSON.parse(text) as T; } catch { return {} as T; }
}, },
[base] [base, getState]
); );
const listProducts = useCallback(async (): Promise<CoffeeItem[]> => { const listProducts = useCallback(async (): Promise<CoffeeItem[]> => {
@ -72,7 +73,7 @@ export default function useCoffeeManagement() {
return data.map((r: any) => ({ return data.map((r: any) => ({
...r, ...r,
id: Number(r.id), id: Number(r.id),
price: r.price != null && r.price !== '' ? Number(r.price) : 0, price: r.price != null && r.price !== '' ? Number(r.price) * CAPSULES_PER_PACK : 0,
interval_count: r.interval_count != null && r.interval_count !== '' ? Number(r.interval_count) : null, interval_count: r.interval_count != null && r.interval_count !== '' ? Number(r.interval_count) : null,
state: !!r.state, state: !!r.state,
})) as CoffeeItem[]; })) as CoffeeItem[];
@ -91,7 +92,7 @@ export default function useCoffeeManagement() {
const appendBaseFields = (fd: FormData) => { const appendBaseFields = (fd: FormData) => {
fd.append('title', payload.title); fd.append('title', payload.title);
fd.append('description', payload.description); fd.append('description', payload.description);
fd.append('price', String(payload.price)); fd.append('price', String(payload.price / CAPSULES_PER_PACK));
if (payload.currency) fd.append('currency', payload.currency); if (payload.currency) fd.append('currency', payload.currency);
if (typeof payload.is_featured === 'boolean') fd.append('is_featured', String(payload.is_featured)); if (typeof payload.is_featured === 'boolean') fd.append('is_featured', String(payload.is_featured));
if (typeof payload.state === 'boolean') fd.append('state', String(payload.state)); if (typeof payload.state === 'boolean') fd.append('state', String(payload.state));
@ -140,7 +141,7 @@ export default function useCoffeeManagement() {
const fd = new FormData(); const fd = new FormData();
if (payload.title !== undefined) fd.append('title', String(payload.title)); if (payload.title !== undefined) fd.append('title', String(payload.title));
if (payload.description !== undefined) fd.append('description', String(payload.description)); if (payload.description !== undefined) fd.append('description', String(payload.description));
if (payload.price !== undefined) fd.append('price', String(payload.price)); if (payload.price !== undefined) fd.append('price', String(payload.price / CAPSULES_PER_PACK));
if (payload.currency !== undefined) fd.append('currency', payload.currency); if (payload.currency !== undefined) fd.append('currency', payload.currency);
if (payload.is_featured !== undefined) fd.append('is_featured', String(payload.is_featured)); if (payload.is_featured !== undefined) fd.append('is_featured', String(payload.is_featured));
if (payload.state !== undefined) fd.append('state', String(payload.state)); if (payload.state !== undefined) fd.append('state', String(payload.state));