updates on the redesign page for all the pages
This commit is contained in:
@@ -1,130 +1,603 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import { Stack, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, Chip } from '@mui/material';
|
||||
import MainCard from 'components/MainCard';
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Grid,
|
||||
Paper,
|
||||
Stack,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import {
|
||||
MdLocalOffer,
|
||||
MdMyLocation,
|
||||
MdAttachMoney,
|
||||
MdGroups,
|
||||
MdPlace,
|
||||
MdSpeed,
|
||||
MdPriceCheck,
|
||||
MdStraighten,
|
||||
MdReceiptLong
|
||||
} from 'react-icons/md';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import Loader from 'components/Loader';
|
||||
import TitleCard from 'components/nearle_components/TitleCard';
|
||||
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
||||
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||
import { Empty } from 'antd';
|
||||
import { OrdersTableSkeleton } from '../orders/OrdersTableSkeleton';
|
||||
import { getallpricing } from 'pages/api/api';
|
||||
|
||||
// ============================================================================
|
||||
// Design tokens — shared with the deliveries / tenants / customers pages so every
|
||||
// surface (header, KPI tiles, table, badges) speaks the same visual language.
|
||||
// Keep this block in sync with customers.js / deliveries.js.
|
||||
// ============================================================================
|
||||
const DT = {
|
||||
radiusPill: 999,
|
||||
radiusCard: 16,
|
||||
shadowSoft: '0 14px 40px rgba(15, 23, 42, 0.10)',
|
||||
shadowMd: '0 8px 24px rgba(15, 23, 42, 0.08)',
|
||||
shadowPop: '0 18px 50px rgba(15, 23, 42, 0.18)',
|
||||
textPrimary: '#0f172a',
|
||||
textSecondary: '#64748b',
|
||||
textMuted: '#94a3b8',
|
||||
borderSubtle: '#e2e8f0',
|
||||
divider: '#f1f5f9',
|
||||
surface: '#ffffff',
|
||||
surfaceAlt: '#f8fafc'
|
||||
};
|
||||
const a = (c, suffix) => `${c}${suffix}`;
|
||||
const tint = (c) => a(c, '08');
|
||||
const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
{...props}
|
||||
sx={{
|
||||
mt: 0.75,
|
||||
borderRadius: 2,
|
||||
boxShadow: DT.shadowPop,
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||||
<Avatar
|
||||
sx={{
|
||||
width: size,
|
||||
height: size,
|
||||
bgcolor: selected ? color : soft(color),
|
||||
color: selected ? '#fff' : color,
|
||||
transition: 'background-color 0.15s, color 0.15s'
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Avatar>
|
||||
);
|
||||
|
||||
const formatRupees = (value) =>
|
||||
new Intl.NumberFormat('en-IN', {
|
||||
style: 'currency',
|
||||
currency: 'INR',
|
||||
minimumFractionDigits: 2
|
||||
}).format(Number(value) || 0);
|
||||
|
||||
const formatDecimal = (value) =>
|
||||
new Intl.NumberFormat('en-IN', { minimumFractionDigits: 2 }).format(Number(value) || 0);
|
||||
|
||||
// Soft pill for metric cells in the table.
|
||||
const MetricPill = ({ color, icon, label, width }) => (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
px: 1,
|
||||
py: 0.375,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint(color),
|
||||
border: `1px solid ${edge(color)}`,
|
||||
color,
|
||||
fontSize: 11,
|
||||
fontWeight: 800,
|
||||
minWidth: width,
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
</Box>
|
||||
);
|
||||
|
||||
// ==============================|| Pricing page ||============================== //
|
||||
|
||||
// ==============================|| Starts here ||============================== //
|
||||
const ClientsPricing = () => {
|
||||
const containerRef = useRef();
|
||||
const [appId, setAppId] = useState(0);
|
||||
const [locaName, setLocoName] = useState('');
|
||||
const [pricing, setpricing] = useState([]);
|
||||
const [isLoader, setIsloader] = useState([]);
|
||||
const [locaName, setLocoName] = useState('All');
|
||||
const [searchword, setSearchword] = useState('');
|
||||
const [debouncedSearch, setDebouncedSearch] = useState('');
|
||||
|
||||
// ==============================|| formatNumberToRupees ||============================== //
|
||||
function formatNumberToRupees(value) {
|
||||
return new Intl.NumberFormat('en-IN', {
|
||||
style: 'currency',
|
||||
currency: 'INR',
|
||||
minimumFractionDigits: 2
|
||||
}).format(value);
|
||||
}
|
||||
function dotzerozero(value) {
|
||||
return new Intl.NumberFormat('en-IN', {
|
||||
minimumFractionDigits: 2
|
||||
}).format(value);
|
||||
}
|
||||
const {
|
||||
data: pricing = [],
|
||||
isLoading
|
||||
} = useQuery({
|
||||
queryKey: ['getallpricing', appId],
|
||||
queryFn: getallpricing,
|
||||
keepPreviousData: true
|
||||
});
|
||||
|
||||
// ==============================|| getAllPricing ||============================== //
|
||||
const getAllPricing = async () => {
|
||||
setIsloader(true);
|
||||
try {
|
||||
const pricingres = await axios.get(`${process.env.REACT_APP_URL}/utils/getallpricing/?applocationid=${appId}`);
|
||||
console.log('pricingres', pricingres.data.details);
|
||||
setpricing(pricingres.data.details);
|
||||
setIsloader(false);
|
||||
} catch (err) {
|
||||
console.log('pricingres', err);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
getAllPricing();
|
||||
}, [appId]);
|
||||
const rows = useMemo(() => {
|
||||
if (!debouncedSearch) return pricing;
|
||||
const q = debouncedSearch.toLowerCase().trim();
|
||||
return pricing.filter((row) =>
|
||||
[row.applocation, row.appname, row.slab, String(row.pricingid)]
|
||||
.filter(Boolean)
|
||||
.some((field) => String(field).toLowerCase().includes(q))
|
||||
);
|
||||
}, [pricing, debouncedSearch]);
|
||||
|
||||
const stats = useMemo(() => {
|
||||
const total = pricing.length;
|
||||
const tenants = new Set(pricing.map((r) => r.appname).filter(Boolean)).size;
|
||||
const avgBase = total
|
||||
? pricing.reduce((sum, r) => sum + (Number(r.baseprice) || 0), 0) / total
|
||||
: 0;
|
||||
return { total, tenants, avgBase };
|
||||
}, [pricing]);
|
||||
|
||||
const KPI_META = [
|
||||
{ key: 'total', label: 'Total Pricing Slabs', color: BRAND, icon: MdLocalOffer, value: stats.total },
|
||||
{ key: 'tenants', label: 'Tenants Priced', color: '#0ea5e9', icon: MdGroups, value: stats.tenants },
|
||||
{ key: 'avg', label: 'Avg Base Price', color: '#f59e0b', icon: MdAttachMoney, value: formatRupees(stats.avgBase) },
|
||||
{ key: 'zone', label: 'Active Zone', color: '#10b981', icon: MdPlace, value: locaName || 'All Zones' }
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoader && <Loader />}
|
||||
{/* ============================================= || Title Card || ============================================= */}
|
||||
<Stack direction={'row'} justifyContent="space-between" alignItems="center" sx={{ my: 1 }}>
|
||||
<TitleCard title="Pricing" />
|
||||
<Stack sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
|
||||
{isLoading && <Loader />}
|
||||
|
||||
{/* ============================================= || Header || ============================================= */}
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
mb: { xs: 1.5, md: 2 },
|
||||
p: { xs: 1.5, sm: 2, md: 2.5 },
|
||||
borderRadius: DT.radiusCard / 8,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
|
||||
boxShadow: DT.shadowMd
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
alignItems={{ xs: 'flex-start', sm: 'center' }}
|
||||
justifyContent="space-between"
|
||||
spacing={{ xs: 1.5, sm: 2 }}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={{ xs: 1.25, sm: 1.75 }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: { xs: 40, sm: 48 },
|
||||
height: { xs: 40, sm: 48 },
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
boxShadow: `0 6px 18px ${ring(BRAND)}`
|
||||
}}
|
||||
>
|
||||
<MdLocalOffer size={22} />
|
||||
</Avatar>
|
||||
<Stack>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
color: DT.textPrimary,
|
||||
lineHeight: 1.1,
|
||||
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.75rem' }
|
||||
}}
|
||||
>
|
||||
Pricing
|
||||
</Typography>
|
||||
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ mt: 0.5 }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: '50%',
|
||||
bgcolor: '#10b981',
|
||||
boxShadow: '0 0 0 4px rgba(16,185,129,0.18)'
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
||||
Live · {locaName || 'All Zones'}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<LocationAutocomplete
|
||||
locaName={locaName}
|
||||
setAppId={setAppId}
|
||||
setLocoName={setLocoName}
|
||||
sx={{ width: { xs: '100%', custom450: 300 }, zIndex: '100' }}
|
||||
pill
|
||||
accentColor={BRAND}
|
||||
icon={<MdMyLocation size={14} />}
|
||||
placeholder="Select Zone"
|
||||
paperComponent={SoftPaper}
|
||||
sx={{ width: { xs: '100%', sm: 280 }, zIndex: 100 }}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{/* ============================================= || table || ============================================= */}
|
||||
<MainCard content={false} sx={{ mt: 2 }}>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead sx={{ bgcolor: '#e1bee7' }}>
|
||||
<TableRow>
|
||||
<TableCell>S.No</TableCell>
|
||||
<TableCell>Location</TableCell>
|
||||
<TableCell align="center">Pricing Id</TableCell>
|
||||
<TableCell>Name</TableCell>
|
||||
</Paper>
|
||||
|
||||
{/* ============================================= || KPI Cards || ============================================= */}
|
||||
<Grid container spacing={{ xs: 1.25, sm: 1.5, md: 2 }} sx={{ mt: '1px' }}>
|
||||
{KPI_META.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<Grid item key={item.key} xs={12} sm={6} md={3}>
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
p: { xs: 1.25, sm: 1.75, md: 2.25 },
|
||||
borderRadius: DT.radiusCard / 8,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: '#fff',
|
||||
transition: 'transform 0.2s, box-shadow 0.2s, border-color 0.2s',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-3px)',
|
||||
boxShadow: DT.shadowMd,
|
||||
borderColor: edge(item.color)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 3,
|
||||
background: `linear-gradient(90deg, ${item.color} 0%, ${soft(item.color)} 100%)`
|
||||
}}
|
||||
/>
|
||||
<Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}>
|
||||
<Stack spacing={0.5} sx={{ minWidth: 0, flex: 1 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{
|
||||
color: DT.textSecondary,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.4,
|
||||
textTransform: 'uppercase',
|
||||
fontSize: { xs: 10, sm: 11 },
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
color: DT.textPrimary,
|
||||
lineHeight: 1.1,
|
||||
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.75rem' },
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}}
|
||||
>
|
||||
{item.value}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: { xs: 36, sm: 42, md: 48 },
|
||||
height: { xs: 36, sm: 42, md: 48 },
|
||||
bgcolor: soft(item.color),
|
||||
color: item.color,
|
||||
boxShadow: `inset 0 0 0 1px ${edge(item.color)}`,
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<Icon size={20} />
|
||||
</Avatar>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
|
||||
{/* ============================================= || Search Header || ============================================= */}
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
mt: { xs: 1.5, md: 2 },
|
||||
p: { xs: 1, md: 1.5 },
|
||||
borderTopLeftRadius: DT.radiusCard / 8,
|
||||
borderTopRightRadius: DT.radiusCard / 8,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
borderBottom: 0,
|
||||
background: '#fff'
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
alignItems={{ xs: 'stretch', sm: 'center' }}
|
||||
justifyContent="space-between"
|
||||
spacing={1.25}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1.25}>
|
||||
<AccentAvatar color={BRAND} size={32}>
|
||||
<MdLocalOffer size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{ fontWeight: 800, color: DT.textSecondary, letterSpacing: 0.6, textTransform: 'uppercase' }}
|
||||
>
|
||||
Pricing Catalog
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: DT.textPrimary, fontWeight: 700 }}>
|
||||
{pricing.length} total · {rows.length} shown
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Box sx={{ width: { xs: '100%', sm: 280, lg: 340 }, flex: { xs: '1 1 100%', sm: '0 0 auto' } }}>
|
||||
<DebounceSearchBar
|
||||
value={searchword}
|
||||
onChange={setSearchword}
|
||||
onDebouncedChange={setDebouncedSearch}
|
||||
placeholder={`Search pricing (ctrl+k)`}
|
||||
sx={{
|
||||
m: 0,
|
||||
width: '100%',
|
||||
borderRadius: 999,
|
||||
bgcolor: tint(BRAND),
|
||||
'& fieldset': { borderColor: edge(BRAND), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: BRAND },
|
||||
'&.Mui-focused fieldset': { borderColor: BRAND, borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
{/* ============================================= || Table || ============================================= */}
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomLeftRadius: DT.radiusCard / 8,
|
||||
borderBottomRightRadius: DT.radiusCard / 8,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
overflow: 'hidden',
|
||||
background: '#fff'
|
||||
}}
|
||||
>
|
||||
<TableContainer
|
||||
ref={containerRef}
|
||||
sx={{
|
||||
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
|
||||
'&::-webkit-scrollbar': { width: 10, height: 10 },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: edge(BRAND),
|
||||
borderRadius: 8,
|
||||
'&:hover': { backgroundColor: BRAND }
|
||||
},
|
||||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||
}}
|
||||
>
|
||||
<Table stickyHeader sx={{ minWidth: { xs: 860, md: 1080 } }}>
|
||||
<TableHead>
|
||||
<TableRow
|
||||
sx={{
|
||||
'& th': {
|
||||
backgroundColor: DT.surfaceAlt,
|
||||
color: DT.textSecondary,
|
||||
fontSize: { xs: 10, md: 11 },
|
||||
fontWeight: 800,
|
||||
letterSpacing: 0.6,
|
||||
textTransform: 'uppercase',
|
||||
whiteSpace: 'nowrap',
|
||||
borderBottom: `1px solid ${DT.borderSubtle}`,
|
||||
py: { xs: 1, md: 1.25 },
|
||||
px: { xs: 1, md: 2 }
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TableCell>#</TableCell>
|
||||
<TableCell>Tenant</TableCell>
|
||||
<TableCell>Zone</TableCell>
|
||||
<TableCell>Slab</TableCell>
|
||||
<TableCell align="center">Base Price</TableCell>
|
||||
<TableCell align="center">MinKm</TableCell>
|
||||
<TableCell align="center">Price/Km</TableCell>
|
||||
<TableCell align="center">MaxKm</TableCell>
|
||||
<TableCell>Min Orders</TableCell>
|
||||
<TableCell align="center">Min KM</TableCell>
|
||||
<TableCell align="center">Price / KM</TableCell>
|
||||
<TableCell align="center">Max KM</TableCell>
|
||||
<TableCell align="center">Min Orders</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{isLoader && <OrdersTableSkeleton col={5} />}
|
||||
{pricing?.length === 0 && !isLoader ? (
|
||||
{isLoading && <OrdersTableSkeleton col={5} />}
|
||||
{rows.length === 0 && !isLoading ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={10} align="center">
|
||||
<Empty description={'No Pricing List'} />
|
||||
<TableCell colSpan={9} sx={{ py: 6 }}>
|
||||
<Stack alignItems="center" spacing={1.5}>
|
||||
<Avatar sx={{ width: 64, height: 64, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
||||
<MdLocalOffer size={28} />
|
||||
</Avatar>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
||||
No pricing to show
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||||
{searchword ? 'Try a different keyword.' : 'Pick a zone above to load the catalog.'}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
pricing?.map((data, index) => (
|
||||
<TableRow key={data.pricingid || index}>
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
|
||||
<TableCell>{data.applocation}</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip size="small" color="info" label={data.pricingid} sx={{ width: 50 }} />
|
||||
rows.map((row, index) => (
|
||||
<TableRow
|
||||
key={row.pricingid || `${row.appname}-${index}`}
|
||||
sx={{
|
||||
transition: 'background-color 0.15s',
|
||||
'& td': {
|
||||
borderBottom: `1px solid ${DT.divider}`,
|
||||
py: { xs: 1, md: 1.5 },
|
||||
px: { xs: 1, md: 2 }
|
||||
},
|
||||
'&:hover': { backgroundColor: DT.surfaceAlt }
|
||||
}}
|
||||
>
|
||||
<TableCell>
|
||||
<Typography variant="caption" sx={{ fontWeight: 700, color: DT.textMuted }}>
|
||||
{String(index + 1).padStart(2, '0')}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
|
||||
<TableCell sx={{ whiteSpace: 'nowrap' }}>{data.appname}</TableCell>
|
||||
<TableCell>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<AccentAvatar color={BRAND} size={36}>
|
||||
<MdGroups size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ fontWeight: 700, color: DT.textPrimary, whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{row.appname || '—'}
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
||||
ID #{row.pricingid}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{data.slab}</TableCell>
|
||||
<TableCell>
|
||||
{row.applocation ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
px: 1,
|
||||
py: 0.375,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#10b981'),
|
||||
border: `1px solid ${edge('#10b981')}`,
|
||||
color: '#10b981',
|
||||
fontSize: 11,
|
||||
fontWeight: 800
|
||||
}}
|
||||
>
|
||||
<MdPlace size={12} /> {row.applocation}
|
||||
</Box>
|
||||
) : (
|
||||
<Typography variant="caption" sx={{ color: DT.textMuted }}>—</Typography>
|
||||
)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip size="small" color="primary" label={formatNumberToRupees(data.baseprice)} sx={{ width: 100 }} />
|
||||
<TableCell>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
px: 1,
|
||||
py: 0.375,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#0ea5e9'),
|
||||
border: `1px solid ${edge('#0ea5e9')}`,
|
||||
color: '#0ea5e9',
|
||||
fontSize: 11,
|
||||
fontWeight: 800
|
||||
}}
|
||||
>
|
||||
<MdSpeed size={12} /> {row.slab || '—'}
|
||||
</Box>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip size="small" color="warning" label={dotzerozero(data.minkm)} sx={{ width: 100 }} />
|
||||
<MetricPill
|
||||
color={BRAND}
|
||||
icon={<MdPriceCheck size={12} />}
|
||||
label={formatRupees(row.baseprice)}
|
||||
width={110}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip size="small" color="success" label={formatNumberToRupees(data.priceperkm)} sx={{ width: 100 }} />
|
||||
<MetricPill
|
||||
color="#f59e0b"
|
||||
icon={<MdStraighten size={12} />}
|
||||
label={`${formatDecimal(row.minkm)} km`}
|
||||
width={90}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Chip size="small" color="error" label={dotzerozero(data.maxkm)} sx={{ width: 100 }} />
|
||||
<MetricPill
|
||||
color="#10b981"
|
||||
icon={<MdAttachMoney size={12} />}
|
||||
label={formatRupees(row.priceperkm)}
|
||||
width={110}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{data.minorder}</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricPill
|
||||
color="#ef4444"
|
||||
icon={<MdStraighten size={12} />}
|
||||
label={`${formatDecimal(row.maxkm)} km`}
|
||||
width={90}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell align="center">
|
||||
<Stack direction="row" alignItems="center" justifyContent="center" spacing={0.5}>
|
||||
<MdReceiptLong size={14} color={DT.textMuted} />
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ fontWeight: 700, color: DT.textPrimary, whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{row.minorder ?? '—'}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</MainCard>
|
||||
</Paper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user