@@ -27,6 +27,7 @@ import {
2727 type SalesChannel as SalesChannelType ,
2828} from '@/modules/kitchen/services/channelRateService'
2929import { supabase } from '@/lib/supabase'
30+ import { fmtPct } from '@/lib/format'
3031import type { MenuItem } from '@/types/kitchen'
3132
3233function fmtEur ( value : number | null | undefined ) : string {
@@ -128,17 +129,17 @@ export default function EconomiaTab({ item }: EconomiaTabProps) {
128129 < div className = "bg-stone-50 rounded-lg px-4 py-3" >
129130 < div className = "text-[10px] font-medium text-stone-400 tracking-widest uppercase mb-1" > PVP cliente</ div >
130131 < div className = "font-mono text-lg font-medium" > { fmtEur ( pvpConIva ) } </ div >
131- < div className = "text-[11px] text-stone-400" > IVA { vatPct } % incluido</ div >
132+ < div className = "text-[11px] text-stone-400" > IVA { fmtPct ( vatPct ) } incluido</ div >
132133 </ div >
133134 < div className = "bg-stone-50 rounded-lg px-4 py-3" >
134- < div className = "text-[10px] font-medium text-stone-400 tracking-widest uppercase mb-1" > Food cost </ div >
135+ < div className = "text-[10px] font-medium text-stone-400 tracking-widest uppercase mb-1" > Coste de producto </ div >
135136 < div className = { `font-mono text-lg font-medium ${ hasCost ? 'text-[#BA7517]' : 'text-stone-300' } ` } > { hasCost ? fmtEur ( recipeCost ) : '—' } </ div >
136- < div className = "text-[11px] text-stone-400" > { hasCost ? `${ foodCostPct } % del PVP` : 'Pendiente de escandallo' } </ div >
137+ < div className = "text-[11px] text-stone-400" > { hasCost ? `${ fmtPct ( foodCostPct , 2 ) } del PVP` : 'Pendiente de escandallo' } </ div >
137138 </ div >
138139 < div className = "bg-stone-50 rounded-lg px-4 py-3" >
139140 < div className = "text-[10px] font-medium text-stone-400 tracking-widest uppercase mb-1" > Mejor margen</ div >
140141 < div className = { `font-mono text-lg font-medium ${ bestMargin != null ? 'text-success' : 'text-stone-300' } ` } > { bestMargin != null ? fmtEur ( bestMargin ) : '—' } </ div >
141- < div className = "text-[11px] text-stone-400" > { bestChannel ? `${ bestChannel } · ${ bestMarginPct } % ` : 'Configura un canal' } </ div >
142+ < div className = "text-[11px] text-stone-400" > { bestChannel ? `${ bestChannel } · ${ fmtPct ( bestMarginPct , 2 ) } ` : 'Configura un canal' } </ div >
142143 </ div >
143144 </ div >
144145
@@ -176,12 +177,12 @@ export default function EconomiaTab({ item }: EconomiaTabProps) {
176177 < div className = "flex items-center gap-2.5" > { badge } </ div >
177178 < div className = "text-right" >
178179 < span className = { `font-mono text-xl font-medium ${ margin >= 0 ? 'text-success' : 'text-danger' } ` } > { fmtEur ( margin ) } </ span >
179- < div className = "text-[12px] text-stone-400" > { marginPct } % del PVP{ ! e . costAvailable ? ' · sin food cost ' : '' } </ div >
180+ < div className = "text-[12px] text-stone-400" > { fmtPct ( marginPct , 2 ) } del PVP{ ! e . costAvailable ? ' · sin coste de producto ' : '' } </ div >
180181 </ div >
181182 </ div >
182183 < div className = "flex flex-wrap gap-x-4 gap-y-1 mb-2 text-[12px] text-stone-500" >
183- { e . costAvailable && < span className = "flex items-center gap-1.5" > < span className = "w-2 h-2 rounded-sm bg-[#A68B6B]" /> Food cost { fmtEur ( e . cost ) } </ span > }
184- { e . commissionPct != null && < span className = "flex items-center gap-1.5" > < span className = "w-2 h-2 rounded-sm bg-[#4A6A8A]" /> Comisión { e . commissionPct } % ({ fmtEur ( commAmt ) } )</ span > }
184+ { e . costAvailable && < span className = "flex items-center gap-1.5" > < span className = "w-2 h-2 rounded-sm bg-[#A68B6B]" /> Coste de producto { fmtEur ( e . cost ) } </ span > }
185+ { e . commissionPct != null && < span className = "flex items-center gap-1.5" > < span className = "w-2 h-2 rounded-sm bg-[#4A6A8A]" /> Comisión { fmtPct ( e . commissionPct ) } ({ fmtEur ( commAmt ) } )</ span > }
185186 { hasOrderCosts && (
186187 < span className = "flex items-center gap-1.5 cursor-help"
187188 title = { `Coste de reparto propio por pedido: coste del rider${ e . ownCourierCost != null ? ` (${ fmtEur ( e . ownCourierCost ) } )` : '' } + comisión fija${ e . commissionFixed != null ? ` (${ fmtEur ( e . commissionFixed ) } )` : '' } − envío que paga el cliente${ e . ownCustomerFee != null ? ` (${ fmtEur ( e . ownCustomerFee ) } )` : '' } , sin IVA, repartido entre ~2 platos por pedido. Es una estimación hasta tener ventas reales.` } >
@@ -214,8 +215,8 @@ export default function EconomiaTab({ item }: EconomiaTabProps) {
214215 prop, así que no hay ventana de desincronización). */ }
215216 < p className = "text-[12px] text-stone-500 mt-4 pt-3 border-t border-stone-200" >
216217 { item . targetFoodCostPct != null
217- ? `Target FC : ${ item . targetFoodCostPct } % · ${ foodCostPct != null ? ( foodCostPct <= item . targetFoodCostPct ? 'Dentro del objetivo' : 'Fuera del objetivo' ) : 'sin food cost para comparar' } `
218- : 'Sin target de food cost configurado.' }
218+ ? `Objetivo de coste : ${ fmtPct ( item . targetFoodCostPct ) } · ${ foodCostPct != null ? ( foodCostPct <= item . targetFoodCostPct ? 'Dentro del objetivo' : 'Fuera del objetivo' ) : 'sin coste de producto para comparar' } `
219+ : 'Sin objetivo de coste configurado.' }
219220 </ p >
220221 </ div >
221222 )
0 commit comments