form issue fixed
This commit is contained in:
parent
c75e3e0107
commit
761653da47
@ -58,6 +58,85 @@ export function OrderCard({ row, fields, isDetailView = false }: { row: Record<s
|
|||||||
const totalKgs = formatValue(totalKgsVal);
|
const totalKgs = formatValue(totalKgsVal);
|
||||||
const totalBags = formatValue(totalBagsVal);
|
const totalBags = formatValue(totalBagsVal);
|
||||||
|
|
||||||
|
const productsSection = gridVal.length > 0 ? (
|
||||||
|
<div style={{
|
||||||
|
marginTop: '16px',
|
||||||
|
backgroundColor: '#FFFBF4',
|
||||||
|
border: '1px solid #e2e8f0',
|
||||||
|
borderRadius: '16px',
|
||||||
|
padding: '16px'
|
||||||
|
}}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '16px' }}>
|
||||||
|
<div style={{ backgroundColor: '#e6f9ed', padding: '6px', borderRadius: '50%' }}>
|
||||||
|
<Package size={16} color="#0d7d81" />
|
||||||
|
</div>
|
||||||
|
<span style={{ color: '#0d7d81', fontWeight: 600, fontSize: '13px', letterSpacing: '0.05em' }}>
|
||||||
|
ORDER PRODUCTS
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
||||||
|
{gridVal.map((item, i) => {
|
||||||
|
const getVal = (key: string) => {
|
||||||
|
if (item[key] !== undefined) return item[key];
|
||||||
|
const keyPattern = new RegExp(`^${key}(_\\d+)?$`);
|
||||||
|
const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key));
|
||||||
|
return match ? item[match] : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product');
|
||||||
|
const skuCodeRaw = getVal('sku_code') || getVal('item_code') || '';
|
||||||
|
const skuCode = isNaN(Number(skuCodeRaw)) || String(skuCodeRaw).length > 3 ? formatValue(skuCodeRaw) : '';
|
||||||
|
const category = formatValue(getVal('product_category') || '');
|
||||||
|
const brCode = formatValue(getVal('br_code') || '');
|
||||||
|
const subtitleArr = [skuCode, category, brCode].filter(v => v && v !== '—');
|
||||||
|
const subtitle = subtitleArr.join(' . ').toUpperCase();
|
||||||
|
|
||||||
|
const bagsStr = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
||||||
|
const bagsNum = Number(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
||||||
|
const skuNum = Number(getVal('sku') || 0);
|
||||||
|
const kgsNum = skuNum > 0 ? skuNum * bagsNum : Number(getVal('row_kgs') || getVal('kgs') || getVal('weight') || 0);
|
||||||
|
const kgsStr = kgsNum > 0 ? `${kgsNum} kg` : '0 kg';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={i} style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#e8fbf0',
|
||||||
|
border: '1px solid #bcecd0',
|
||||||
|
borderRadius: '24px',
|
||||||
|
padding: '12px 20px',
|
||||||
|
}}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||||
|
<span style={{ color: '#086e73', fontWeight: 600, fontSize: '14px' }}>{productName}</span>
|
||||||
|
</div>
|
||||||
|
<div style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
|
||||||
|
<span style={{ color: '#563bd4', fontWeight: 700, fontSize: '14px' }}>{bagsStr} Bags</span>
|
||||||
|
<span style={{ color: '#64748b', fontSize: '13px', marginLeft: '6px' }}>({kgsStr})</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: '8px',
|
||||||
|
padding: '16px 20px',
|
||||||
|
border: '1px dashed #cbd5e1',
|
||||||
|
borderRadius: '24px'
|
||||||
|
}}>
|
||||||
|
<span style={{ color: '#64748b', fontWeight: 600, fontSize: '13px' }}>TOTAL</span>
|
||||||
|
<div>
|
||||||
|
<span style={{ color: '#563bd4', fontWeight: 700, fontSize: '15px' }}>{totalBags} Bags</span>
|
||||||
|
<span style={{ color: '#64748b', fontSize: '14px', marginLeft: '6px' }}>({totalKgs} kg)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="z-card">
|
<div className="z-card">
|
||||||
<div className="z-card-header">
|
<div className="z-card-header">
|
||||||
@ -88,35 +167,7 @@ export function OrderCard({ row, fields, isDetailView = false }: { row: Record<s
|
|||||||
<span className="z-card-footer-value">{totalKgs} kg</span>
|
<span className="z-card-footer-value">{totalKgs} kg</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{gridVal.length > 0 && (
|
{productsSection}
|
||||||
<div className="z-card-details" style={{ display: 'block', borderTop: '1px solid #f1f5f9' }}>
|
|
||||||
<p className="z-card-meta" style={{ marginBottom: '8px' }}>Order Products</p>
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
||||||
{gridVal.map((item, i) => {
|
|
||||||
const getVal = (key: string) => {
|
|
||||||
if (item[key] !== undefined) return item[key];
|
|
||||||
const keyPattern = new RegExp(`^${key}(_\\d+)?$`);
|
|
||||||
const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key));
|
|
||||||
return match ? item[match] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product');
|
|
||||||
const bagsStr = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
|
||||||
const bagsNum = Number(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
|
||||||
const skuNum = Number(getVal('sku') || 0);
|
|
||||||
const kgsNum = skuNum > 0 ? skuNum * bagsNum : Number(getVal('row_kgs') || getVal('kgs') || getVal('weight') || 0);
|
|
||||||
const kgsStr = kgsNum > 0 ? ` (${kgsNum} kg)` : '';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={i} style={{ display: 'flex', justifyContent: 'space-between', fontSize: '13px', background: '#f8fafc', padding: '8px 12px', borderRadius: '8px' }}>
|
|
||||||
<span style={{ fontWeight: 600, color: '#334155' }}>{productName}</span>
|
|
||||||
<span style={{ fontWeight: 700, color: '#4f46e5' }}>{bagsStr} Bags{kgsStr}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -168,43 +219,10 @@ export function OrderCard({ row, fields, isDetailView = false }: { row: Record<s
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{gridVal.length > 0 && (
|
{productsSection}
|
||||||
<div className="mt-6 border-t border-gray-100 pt-6">
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' }}>
|
|
||||||
<p className="z-card-meta" style={{ margin: 0, color: '#334155', fontWeight: 700 }}>Order Products</p>
|
|
||||||
<span className="text-xs font-bold text-gray-800 bg-gray-100 px-3 py-1 rounded-full border border-gray-200">
|
|
||||||
{totalItems} {totalItems === 1 ? 'Item' : 'Items'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
||||||
{gridVal.map((item, i) => {
|
|
||||||
const getVal = (key: string) => {
|
|
||||||
if (item[key] !== undefined) return item[key];
|
|
||||||
const keyPattern = new RegExp(`^${key}(_\\d+)?$`);
|
|
||||||
const match = Object.keys(item).find(k => keyPattern.test(k) || k.includes(key));
|
|
||||||
return match ? item[match] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const productName = formatValue(getVal('product_name') || getVal('product_category') || 'Unknown Product');
|
|
||||||
const bagsStr = formatValue(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
|
||||||
const bagsNum = Number(getVal('bags') || getVal('total_bags') || getVal('quantity') || 0);
|
|
||||||
const skuNum = Number(getVal('sku') || 0);
|
|
||||||
const kgsNum = skuNum > 0 ? skuNum * bagsNum : Number(getVal('row_kgs') || getVal('kgs') || getVal('weight') || 0);
|
|
||||||
const kgsStr = kgsNum > 0 ? ` (${kgsNum} kg)` : '';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={i} style={{ display: 'flex', justifyContent: 'space-between', fontSize: '14px', background: '#f8fafc', padding: '12px 16px', borderRadius: '8px', border: '1px solid #e2e8f0' }}>
|
|
||||||
<span style={{ fontWeight: 700, color: '#1e293b' }}>{productName}</span>
|
|
||||||
<span style={{ fontWeight: 800, color: '#3730a3' }}>{bagsStr} Bags{kgsStr}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Logistics Totals at the bottom */}
|
{/* Logistics Totals at the bottom */}
|
||||||
{(Number(totalKgsVal) > 0 || Number(totalBagsVal) > 0) && (
|
{gridVal.length === 0 && (Number(totalKgsVal) > 0 || Number(totalBagsVal) > 0) && (
|
||||||
<div className="mt-4 flex justify-between items-center bg-gray-50 p-4 rounded-xl border border-gray-200 shadow-sm">
|
<div className="mt-4 flex justify-between items-center bg-gray-50 p-4 rounded-xl border border-gray-200 shadow-sm">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="text-[11px] uppercase tracking-wider font-bold text-gray-700">Total Weight</span>
|
<span className="text-[11px] uppercase tracking-wider font-bold text-gray-700">Total Weight</span>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
.z-card {
|
.z-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--z-bg-neutral-100);
|
background-color: #FFFBF4;
|
||||||
border-radius: var(--block-radius);
|
border-radius: var(--block-radius);
|
||||||
padding: var(--block-padding);
|
padding: var(--block-padding);
|
||||||
box-shadow: var(--block-shadow);
|
box-shadow: var(--block-shadow);
|
||||||
|
|||||||
@ -121,7 +121,7 @@ export function OrderDetail({ instanceId, onDataLoad, onBack }: WiredDetailViewP
|
|||||||
const totalKgs = extract('total_kgs_3', remainingData) || 0;
|
const totalKgs = extract('total_kgs_3', remainingData) || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4 bg-[var(--tiles-card-bg)] p-1">
|
<div className="flex flex-col gap-4 bg-transparent p-1">
|
||||||
{/* Top Section */}
|
{/* Top Section */}
|
||||||
<div className="border border-slate-200 rounded-xl p-6 bg-[var(--tiles-card-bg)] shadow-sm flex flex-col md:flex-row md:items-start justify-between gap-4">
|
<div className="border border-slate-200 rounded-xl p-6 bg-[var(--tiles-card-bg)] shadow-sm flex flex-col md:flex-row md:items-start justify-between gap-4">
|
||||||
<div className="flex items-center gap-3 mb-1">
|
<div className="flex items-center gap-3 mb-1">
|
||||||
@ -176,59 +176,73 @@ export function OrderDetail({ instanceId, onDataLoad, onBack }: WiredDetailViewP
|
|||||||
{/* Bottom Section */}
|
{/* Bottom Section */}
|
||||||
<div className="flex flex-col lg:flex-row gap-4">
|
<div className="flex flex-col lg:flex-row gap-4">
|
||||||
{/* Left Table */}
|
{/* Left Table */}
|
||||||
<div className="flex-[2] border border-slate-200 rounded-xl bg-[var(--tiles-card-bg)] shadow-sm overflow-hidden flex flex-col min-w-0">
|
<div className="flex-[2] border border-slate-200 rounded-xl bg-[var(--tiles-card-bg)] shadow-sm overflow-hidden flex flex-col min-w-0" style={{ padding: '20px' }}>
|
||||||
<div className="p-4 border-b border-slate-100 flex items-center gap-2 bg-slate-50">
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '20px' }}>
|
||||||
<Package size={14} className="text-slate-500" />
|
<div style={{ backgroundColor: '#e6f9ed', padding: '6px', borderRadius: '50%' }}>
|
||||||
<span className="text-xs font-bold text-slate-500 uppercase tracking-wider">Order Items</span>
|
<Package size={16} color="#0d7d81" />
|
||||||
|
</div>
|
||||||
|
<span style={{ color: '#0d7d81', fontWeight: 600, fontSize: '13px', letterSpacing: '0.05em' }}>
|
||||||
|
ORDER PRODUCTS
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-y-auto p-4 flex flex-col gap-3 bg-slate-50">
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
||||||
{itemsArray.map((item: any, idx: number) => {
|
{itemsArray.map((item: any, idx: number) => {
|
||||||
const product = item.product_name_3 || '-';
|
const productName = String(item.product_name_3 || item.product_name || 'Unknown Product');
|
||||||
const category = item.product_category_3 || '-';
|
const skuCodeRaw = item.sku_code_3 || item.sku_code || '';
|
||||||
const sku = item.sku_code_3 || '-';
|
const skuCode = isNaN(Number(skuCodeRaw)) || String(skuCodeRaw).length > 3 ? String(skuCodeRaw) : '';
|
||||||
const bags = item.bags_3 || '0';
|
const category = String(item.product_category_3 || item.product_category || '');
|
||||||
const brCode = item.br_code_3 || '-';
|
const brCode = String(item.br_code_3 || item.br_code || '');
|
||||||
const weight = item.sku_3 ? `${item.sku_3} kg` : '-';
|
|
||||||
|
const subtitleArr = [skuCode, category, brCode].filter(v => v && v !== '-' && v !== '—');
|
||||||
|
const subtitle = subtitleArr.join(' . ').toUpperCase();
|
||||||
|
|
||||||
|
const bagsNum = Number(item.bags_3 || item.bags || 0);
|
||||||
|
const bagsStr = String(bagsNum);
|
||||||
|
|
||||||
|
const skuNum = Number(item.sku_3 || item.sku || 0);
|
||||||
|
const rowKgsRaw = item.row_kgs_3 || item.row_kgs || item.weight;
|
||||||
|
const kgsNum = skuNum > 0 ? skuNum * bagsNum : Number(rowKgsRaw || 0);
|
||||||
|
const kgsStr = kgsNum > 0 ? `${kgsNum} kg` : '0 kg';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={idx} className="bg-white rounded-xl border border-slate-200 p-4 shadow-sm flex flex-col gap-3 transition-shadow hover:shadow-md">
|
<div key={idx} style={{
|
||||||
<div className="flex justify-between items-start gap-4 border-b border-slate-50 pb-3">
|
display: 'flex',
|
||||||
<div className="flex flex-col gap-1">
|
justifyContent: 'space-between',
|
||||||
<span className="font-bold text-slate-900 text-sm">{String(product)}</span>
|
alignItems: 'center',
|
||||||
<span className="text-[11px] text-slate-400 font-medium uppercase tracking-wide">{String(category)}</span>
|
backgroundColor: '#e8fbf0',
|
||||||
</div>
|
border: '1px solid #bcecd0',
|
||||||
<span className={`inline-flex items-center px-2 py-0.5 rounded text-[10px] font-bold border uppercase tracking-wider whitespace-nowrap bg-blue-50 text-blue-700 border-blue-200`}>
|
borderRadius: '24px',
|
||||||
{String(sku)}
|
padding: '14px 20px',
|
||||||
</span>
|
}}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||||
|
<span style={{ color: '#086e73', fontWeight: 600, fontSize: '14px' }}>{productName}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
|
||||||
<div className="grid grid-cols-2 gap-3 bg-slate-50 p-3 rounded-lg border border-slate-100">
|
<span style={{ color: '#563bd4', fontWeight: 700, fontSize: '14px' }}>{bagsStr} Bags</span>
|
||||||
<div className="flex flex-col gap-0.5">
|
<span style={{ color: '#64748b', fontSize: '13px', marginLeft: '6px' }}>({kgsStr})</span>
|
||||||
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-wider">Weight</span>
|
|
||||||
<span className="text-sm font-semibold text-slate-700">{String(weight)}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-0.5 border-l border-slate-200 pl-3">
|
|
||||||
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-wider">BR Code</span>
|
|
||||||
<span className="text-sm font-semibold text-slate-700">{String(brCode)}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between p-3 rounded-lg border border-slate-100 bg-white">
|
|
||||||
<div className="flex flex-col gap-0.5">
|
|
||||||
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-wider">Bags</span>
|
|
||||||
<span className="text-lg font-black text-slate-900">{String(bags)}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<div className="mt-2 bg-slate-900 text-white rounded-xl p-4 flex items-center justify-between shadow-sm">
|
|
||||||
<span className="text-xs font-bold uppercase tracking-wider text-slate-400">Total Order</span>
|
{itemsArray.length > 0 && (
|
||||||
<div className="flex flex-col items-end">
|
<div style={{
|
||||||
<span className="text-[10px] font-medium text-slate-400 uppercase">Total Bags</span>
|
display: 'flex',
|
||||||
<span className="text-lg font-black text-emerald-400">{String(totalBags)}</span>
|
justifyContent: 'space-between',
|
||||||
</div>
|
alignItems: 'center',
|
||||||
</div>
|
marginTop: '8px',
|
||||||
|
padding: '16px 20px',
|
||||||
|
border: '1px dashed #cbd5e1',
|
||||||
|
borderRadius: '24px'
|
||||||
|
}}>
|
||||||
|
<span style={{ color: '#64748b', fontWeight: 600, fontSize: '13px' }}>TOTAL</span>
|
||||||
|
<div>
|
||||||
|
<span style={{ color: '#563bd4', fontWeight: 700, fontSize: '15px' }}>{totalBags} Bags</span>
|
||||||
|
<span style={{ color: '#64748b', fontSize: '14px', marginLeft: '6px' }}>({Number(totalKgs).toLocaleString()} kg)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -394,32 +394,34 @@ export function SmartGridField({
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div
|
{!isPotentialMining && (
|
||||||
ref={formRef}
|
<div
|
||||||
className={`grid transition-[grid-template-rows,opacity,margin] duration-300 ease-in-out ${
|
ref={formRef}
|
||||||
!isPotentialMining && editingIdx === null ? 'grid-rows-[1fr] opacity-100 mt-4' : 'grid-rows-[0fr] opacity-0 mt-0'
|
className={`grid transition-[grid-template-rows,opacity,margin] duration-300 ease-in-out ${
|
||||||
}`}
|
editingIdx === null ? 'grid-rows-[1fr] opacity-100 mt-4' : 'grid-rows-[0fr] opacity-0 mt-0 hidden'
|
||||||
>
|
}`}
|
||||||
<div className="overflow-hidden">
|
>
|
||||||
<div className="p-4 border border-border-subtle rounded-xl bg-white shadow-sm">
|
<div className="overflow-hidden min-h-0">
|
||||||
<h4 className="text-sm font-semibold text-strong mb-4 flex items-center gap-2">
|
<div className="p-4 border border-border-subtle rounded-xl bg-white shadow-sm">
|
||||||
Add New Item
|
<h4 className="text-sm font-semibold text-strong mb-4 flex items-center gap-2">
|
||||||
</h4>
|
Add New Item
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 items-end">
|
</h4>
|
||||||
{editingIdx === null && renderFormFields()}
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 items-end">
|
||||||
</div>
|
{editingIdx === null && renderFormFields()}
|
||||||
|
</div>
|
||||||
<div className="flex justify-end gap-2 sm:col-span-2 md:col-span-3 mt-2">
|
|
||||||
<Button type="button" variant="ghost" onClick={() => { setNewRow({}); }}>
|
<div className="flex justify-end gap-2 sm:col-span-2 md:col-span-3 mt-2">
|
||||||
Cancel
|
<Button type="button" variant="ghost" onClick={() => { setNewRow({}); }}>
|
||||||
</Button>
|
Cancel
|
||||||
<Button type="button" variant="primary" onClick={submitNewRow}>
|
</Button>
|
||||||
+ Add to Order
|
<Button type="button" variant="primary" onClick={submitNewRow}>
|
||||||
</Button>
|
+ Add to Order
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,12 +19,13 @@ export interface ModalProps {
|
|||||||
subtitle?: ReactNode;
|
subtitle?: ReactNode;
|
||||||
/** @default "md" */
|
/** @default "md" */
|
||||||
width?: ModalWidth;
|
width?: ModalWidth;
|
||||||
|
maxHeight?: string;
|
||||||
actions?: ReactNode;
|
actions?: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Portal modal host — backdrop, Esc / click-out close, scroll-locked body. */
|
/** Portal modal host — backdrop, Esc / click-out close, scroll-locked body. */
|
||||||
export function Modal({ open, onClose, title, subtitle, width = 'md', actions, children }: ModalProps) {
|
export function Modal({ open, onClose, title, subtitle, width = 'md', maxHeight = 'max-h-[80dvh]', actions, children }: ModalProps) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) return;
|
||||||
const onKey = (e: KeyboardEvent) => {
|
const onKey = (e: KeyboardEvent) => {
|
||||||
@ -53,7 +54,8 @@ export function Modal({ open, onClose, title, subtitle, width = 'md', actions, c
|
|||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative w-full bg-card rounded-t-2xl sm:rounded-lg border border-border-subtle shadow-lg sm:my-auto',
|
'relative w-full bg-card rounded-t-2xl sm:rounded-lg border border-border-subtle shadow-lg sm:my-auto',
|
||||||
'flex flex-col max-h-[70vh]',
|
'flex flex-col',
|
||||||
|
maxHeight,
|
||||||
WIDTH[width],
|
WIDTH[width],
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -76,7 +78,9 @@ export function Modal({ open, onClose, title, subtitle, width = 'md', actions, c
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div className="flex-1 min-h-0 overflow-y-auto p-5 pb-[calc(1.25rem+env(safe-area-inset-bottom))] scrollbar-slim">{children}</div>
|
<div className="shrink min-h-0 overflow-y-auto scrollbar-slim">
|
||||||
|
<div className="p-5 flex flex-col">{children}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
document.body,
|
document.body,
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
background-color: var(--z-bg-neutral-100);
|
background-color: #FFFBF4;
|
||||||
border-radius: var(--z-border-radius-lg, 12px);
|
border-radius: var(--z-border-radius-lg, 12px);
|
||||||
box-shadow: var(--block-shadow);
|
box-shadow: var(--block-shadow);
|
||||||
transition: all 0.2s ease-in-out;
|
transition: all 0.2s ease-in-out;
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export function CallsPage() {
|
|||||||
|
|
||||||
if (instanceId != null) {
|
if (instanceId != null) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full bg-slate-50 w-full relative">
|
<div className="flex flex-col h-full bg-transparent w-full relative">
|
||||||
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
||||||
<CallDetail instanceId={instanceId} onDataLoad={setSelectedRow} onBack={() => { navigate(`/calls`); setIsFabOpen(false); }} />
|
<CallDetail instanceId={instanceId} onDataLoad={setSelectedRow} onBack={() => { navigate(`/calls`); setIsFabOpen(false); }} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -51,7 +51,7 @@ export function ConsoleLayout() {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<nav
|
<nav
|
||||||
className="print:hidden fixed bottom-0 inset-x-0 z-20 h-16 pb-[env(safe-area-inset-bottom)] bg-card border-t border-border-subtle grid shadow-[0_-2px_16px_rgba(11,27,59,0.06)]"
|
className="print:hidden fixed bottom-0 inset-x-0 z-20 h-16 pb-[env(safe-area-inset-bottom)] bg-app border-t border-border-subtle grid shadow-[0_-2px_16px_rgba(11,27,59,0.06)]"
|
||||||
style={{ gridTemplateColumns: `repeat(${SCREENS.filter(t => t.key !== 'analytics' && t.key !== 'all-daily' && t.key !== 'sales-report').length}, minmax(0, 1fr))` }}
|
style={{ gridTemplateColumns: `repeat(${SCREENS.filter(t => t.key !== 'analytics' && t.key !== 'all-daily' && t.key !== 'sales-report').length}, minmax(0, 1fr))` }}
|
||||||
>
|
>
|
||||||
{SCREENS.filter(t => t.key !== 'analytics' && t.key !== 'all-daily' && t.key !== 'sales-report').map((t) => {
|
{SCREENS.filter(t => t.key !== 'analytics' && t.key !== 'all-daily' && t.key !== 'sales-report').map((t) => {
|
||||||
@ -95,10 +95,9 @@ export function ConsoleLayout() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-y-0 left-0 z-50 w-64 bg-card border-r border-border-subtle shadow-xl transform transition-transform duration-300 ease-in-out flex flex-col",
|
"fixed inset-y-0 left-0 z-50 w-64 bg-app border-r border-border-subtle shadow-xl transform transition-transform duration-300 ease-in-out flex flex-col",
|
||||||
isMenuOpen ? "translate-x-0" : "-translate-x-full"
|
isMenuOpen ? "translate-x-0" : "-translate-x-full"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export function OrdersPage() {
|
|||||||
|
|
||||||
if (instanceId != null) {
|
if (instanceId != null) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full bg-slate-50 w-full relative">
|
<div className="flex flex-col h-full bg-transparent w-full relative">
|
||||||
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
||||||
<OrderDetail instanceId={instanceId} onDataLoad={setSelectedRow} onBack={() => { navigate(`/orders`); setIsFabOpen(false); }} />
|
<OrderDetail instanceId={instanceId} onDataLoad={setSelectedRow} onBack={() => { navigate(`/orders`); setIsFabOpen(false); }} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export function StoresPage() {
|
|||||||
|
|
||||||
if (instanceId != null && !isCreating) {
|
if (instanceId != null && !isCreating) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full bg-slate-50 w-full relative">
|
<div className="flex flex-col h-full bg-transparent w-full relative">
|
||||||
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
<div className="flex-1 pb-24 w-full overflow-y-auto">
|
||||||
<StoreDetail instanceId={instanceId} onBack={() => navigate(`/stores`)} />
|
<StoreDetail instanceId={instanceId} onBack={() => navigate(`/stores`)} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -198,7 +198,7 @@
|
|||||||
--font-color: #10182b;
|
--font-color: #10182b;
|
||||||
--font-family: "IBM Plex Sans", serif;
|
--font-family: "IBM Plex Sans", serif;
|
||||||
--light-font-color: #667085;
|
--light-font-color: #667085;
|
||||||
--body-bg: #f0f4f8;
|
--body-bg: #FCF4E7;
|
||||||
--bg-plain: #fff;
|
--bg-plain: #fff;
|
||||||
--bg-active: #00000014;
|
--bg-active: #00000014;
|
||||||
--border: #e5e7eb;
|
--border: #e5e7eb;
|
||||||
@ -298,7 +298,7 @@
|
|||||||
--toolTip-active-clr: #208fe3;
|
--toolTip-active-clr: #208fe3;
|
||||||
|
|
||||||
/* new template style variables */
|
/* new template style variables */
|
||||||
--z-body-bg: #f0f4f8;
|
--z-body-bg: #FCF4E7;
|
||||||
--z-bg-plain: #fff;
|
--z-bg-plain: #fff;
|
||||||
|
|
||||||
--z-bg-primary: #0058be;
|
--z-bg-primary: #0058be;
|
||||||
|
|||||||
@ -68,8 +68,8 @@
|
|||||||
|
|
||||||
/* ---- Semantic aliases (light mode) ---- */
|
/* ---- Semantic aliases (light mode) ---- */
|
||||||
/* Surfaces */
|
/* Surfaces */
|
||||||
--surface-app: var(--slate-50);
|
--surface-app: #FCF4E7;
|
||||||
--surface-card: var(--white);
|
--surface-card: #FFFBF4;
|
||||||
--surface-sunk: var(--slate-100);
|
--surface-sunk: var(--slate-100);
|
||||||
--surface-raised: var(--white);
|
--surface-raised: var(--white);
|
||||||
--surface-navy: var(--navy-900);
|
--surface-navy: var(--navy-900);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user