Finalize CRM module: bookings, pricing, survey with full UI integration and validation

This commit is contained in:
2026-06-22 17:47:36 +05:30
parent 59fc91f034
commit 72a1eb0701
23 changed files with 2620 additions and 326 deletions

View File

@@ -19,42 +19,14 @@ import StatusChip from '@/components/StatusChip';
import DonutChart from '@/components/charts/DonutChart';
import UserAvatar from '@/components/UserAvatar';
import EmptyState from '@/components/EmptyState';
import { fetchPoints, COLLECTIONS } from '@/utils/qdrant';
import bgImage from '@/assets/premium_logistics_bg.png';
const titleCase = (s) =>
String(s || '').replace(/[_-]+/g, ' ').replace(/([a-z\d])([A-Z])/g, '$1 $2').replace(/\b\w/g, (c) => c.toUpperCase()).trim();
import { fetchClients, fetchUsers } from '@/utils/apiClient';
import { toClient, toUser } from '@/utils/mappers';
import { titleCase } from '@/utils/format';
const STATUS_COLOR = { newclient: '#00A2AE', contacted: '#FFBF00', onboarded: '#00A854', lost: '#F04134' };
const statusColor = (s) => STATUS_COLOR[String(s || '').toLowerCase()] || '#8C8C8C';
const BAR_COLORS = ['#C01227', '#00A2AE', '#00A854', '#FFBF00', '#9E0E20', '#8C8C8C', '#D6515C'];
const generateLogicalId = (id) => {
const str = String(id).replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
return 'CLI-' + str.substring(0, 6).padStart(6, '0');
};
function toClient(point) {
const p = point.payload || {};
return {
id: point.id,
logicalId: generateLogicalId(point.id),
name: p.name || '—',
businessType: p.businessType || '',
city: p.city || '',
businessState: p.businessState || '',
status: p.status || 'unknown',
parcelVolume: Number(p.parcelVolume) || 0,
activeContracts: Number(p.activeContracts) || 0,
lastUpdated: p.lastUpdated || ''
};
}
function toUser(point) {
const p = point.payload || {};
return { id: point.id, name: p.name || '—', email: p.email || '', role: p.role || 'unknown' };
}
// Card with a tinted icon header band.
function Panel({ icon: Icon, title, action, color = 'primary', noPadding = false, children }) {
return (
<Card sx={{
@@ -92,10 +64,10 @@ export default function Dashboard() {
const load = () => {
setLoading(true);
setError(null);
Promise.all([fetchPoints(COLLECTIONS.clients), fetchPoints(COLLECTIONS.teamUsers)])
Promise.all([fetchClients(), fetchUsers()])
.then(([cs, us]) => {
setClients(cs.map(toClient));
setTeam(us.map(toUser));
setClients((cs || []).map(toClient));
setTeam((us || []).map(toUser));
})
.catch((e) => setError(e.message || 'Failed to load dashboard data'))
.finally(() => setLoading(false));