// data.jsx — dummy data + RBAC matrix

// === Master data: Categories =========================================
const CATEGORIES = [
  { id: 'mc',  name: 'Mobile Crane',         color: '#0B1F3A' },
  { id: 'sl',  name: 'Skylift',              color: '#2B6CB0' },
  { id: 'scl', name: 'Scissor Lift',         color: '#0E7C66' },
  { id: 'lc',  name: 'Lorry Crane',          color: '#B45309' },
  { id: 'lr',  name: 'Lorry',                color: '#6B4F2A' },
  { id: 'bl',  name: 'Boom Lift',            color: '#7C3AED' },
  { id: 'fl',  name: 'Forklift',             color: '#0F766E' },
  { id: 'rt',  name: 'Rough Terrain Crane',  color: '#9B1C1C' },
  { id: 'cr',  name: 'Cross Rent',           color: '#6D28D9' },
  { id: 'ut',  name: 'Utility',              color: '#475569' },
  { id: 'car', name: 'Car',                  color: '#1D4ED8' },
];

// === Master data: Machines ===========================================
// machine_status: 'available' | 'occupied' | 'unavailable'
//   available  = green dot, ready to assign
//   occupied   = red dot, currently on a booking
//   unavailable= grey dot, in workshop / leave / standby
// Each machine has an `operator` field — the default driver assigned to that
// machine. Used by Create Booking to auto-fill the operator when an available
// machine row is picked from Current Bookings.
const MACHINES = [
  // === MOBILE CRANES + RT CRANE =====================================
  { id: 'PLC-001', name: '8382 (50T)',  plate: 'JSB 8382', category: 'Mobile Crane',         tonnage: '50T',  status: 'occupied',    operator: 'Muthu' },
  { id: 'PLC-002', name: '6382 (45T)',  plate: 'BLR 6382', category: 'Mobile Crane',         tonnage: '45T',  status: 'available',   operator: 'Zorkapli' },
  { id: 'PLC-003', name: '7838 (120T)', plate: 'JYH 7838', category: 'Mobile Crane',         tonnage: '120T', status: 'occupied',    operator: 'Zul30ton' },
  { id: 'PLC-004', name: '1484 (20T)',  plate: 'WHN 1484', category: 'Mobile Crane',         tonnage: '20T',  status: 'available',   operator: 'Hairul' },
  { id: 'PLC-005', name: '9744 (20T)',  plate: 'JGA 9744', category: 'Mobile Crane',         tonnage: '20T',  status: 'occupied',    operator: 'Rajah' },
  { id: 'PLC-006', name: '4758 (20T)',  plate: 'JFW 4758', category: 'Mobile Crane',         tonnage: '20T',  status: 'occupied',    operator: 'Izzul' },
  { id: 'PLC-007', name: '9552 (20T)',  plate: 'WDE 9552', category: 'Mobile Crane',         tonnage: '20T',  status: 'available',   operator: 'Teon' },
  { id: 'PLC-008', name: '8908 (25T)',  plate: 'AMX 8908', category: 'Rough Terrain Crane',  tonnage: '25T',  status: 'occupied',    operator: 'Hisham' },
  { id: 'PLC-009', name: '8569 (20T)',  plate: 'JEF 8569', category: 'Mobile Crane',         tonnage: '20T',  status: 'occupied',    operator: 'Rohezal' },
  { id: 'PLC-010', name: '4368 (20T)',  plate: 'JFR 4368', category: 'Mobile Crane',         tonnage: '20T',  status: 'unavailable', operator: 'Ganis' },
  { id: 'PLC-011', name: '5114 (20T)',  plate: 'JEM 5114', category: 'Mobile Crane',         tonnage: '20T',  status: 'occupied',    operator: 'Kanisan' },
  { id: 'PLC-012', name: '8172 (20T)',  plate: 'JCN 8172', category: 'Mobile Crane',         tonnage: '20T',  status: 'available',   operator: 'Selva' },
  { id: 'PLC-013', name: '284 (20T)',   plate: 'WEC 284',  category: 'Mobile Crane',         tonnage: '20T',  status: 'available',   operator: 'Shafiq' },
  { id: 'PLC-014', name: '239 (20T)',   plate: 'JEQ 239',  category: 'Mobile Crane',         tonnage: '20T',  status: 'occupied',    operator: 'Yusof' },
  { id: 'PLC-015', name: '3135 (7T)',   plate: 'BRS 3135', category: 'Mobile Crane',         tonnage: '7T',   status: 'unavailable', operator: 'Radzi' },

  // === SKYLIFTS =====================================================
  { id: 'PLC-016', name: '5936 (45M)',  plate: 'CEU 5936', category: 'Skylift', tonnage: '45M', status: 'available',  operator: 'Jembri' },
  { id: 'PLC-017', name: '9437 (26M)',  plate: 'BKV 9437', category: 'Skylift', tonnage: '26M', status: 'occupied',   operator: 'Ahmad' },
  { id: 'PLC-018', name: '328 (24M)',   plate: 'BHX 328',  category: 'Skylift', tonnage: '24M', status: 'available',  operator: 'Hanapi' },
  { id: 'PLC-019', name: '2122 (22M)',  plate: 'JMA 2122', category: 'Skylift', tonnage: '22M', status: 'occupied',   operator: 'Azizi' },
  { id: 'PLC-020', name: '9418 (20M)',  plate: 'JEM 9418', category: 'Skylift', tonnage: '20M', status: 'available',  operator: 'Richard' },

  // === SCISSOR LIFT =================================================
  { id: 'SCL-001', name: 'GS-3246.1',   plate: '—',        category: 'Scissor Lift', tonnage: '—', status: 'available', operator: '' },

  // === CROSS RENT (machines rented from other companies) ============
  { id: 'CR-001', name: 'Cross Rent 1', plate: 'Cross Rent 1', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },
  { id: 'CR-002', name: 'Cross Rent 2', plate: 'Cross Rent 2', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },
  { id: 'CR-003', name: 'Cross Rent 3', plate: 'Cross Rent 3', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },
  { id: 'CR-004', name: 'Cross Rent 4', plate: 'Cross Rent 4', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },
  { id: 'CR-005', name: 'Cross Rent 5', plate: 'Cross Rent 5', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },
  { id: 'CR-006', name: 'Cross Rent 6', plate: 'Cross Rent 6', category: 'Cross Rent', tonnage: '—', status: 'available', operator: '' },

  // === CARS (company vehicles) ======================================
  { id: 'CAR-001', name: 'JLU5315', plate: 'JLU5315', category: 'Car', tonnage: '—', status: 'available', operator: '' },
  { id: 'CAR-002', name: 'JJA1906', plate: 'JJA1906', category: 'Car', tonnage: '—', status: 'available', operator: '' },
  { id: 'CAR-003', name: 'JMR3817', plate: 'JMR3817', category: 'Car', tonnage: '—', status: 'available', operator: '' },
  { id: 'CAR-004', name: 'WVT2370', plate: 'WVT2370', category: 'Car', tonnage: '—', status: 'available', operator: '' },
];

// === Machine display label ===========================================
// Every machine is shown across the app by its fleet number + tonnage with
// no space, e.g. "8382(50T)". Non-tonnage assets (scissor lifts, cross rent,
// cars) fall back to their name/plate.
function machineLabel(m) {
  if (!m) return '';
  if (m.tonnage && m.tonnage !== '—') {
    const num = (m.name || '').split(' ')[0]; // numeric fleet no. e.g. "8382"
    return `${num}(${m.tonnage})`;            // → "8382(50T)"
  }
  return (m.plate && m.plate !== '—') ? m.plate : m.name;
}
// Resolve a booking (machine = "PLC-005 …" + bare plate) to the same label.
function bookingMachineLabel(b) {
  const id = ((b && b.machine) || '').split(' ')[0];
  const m = MACHINES.find(x => x.id === id);
  if (m) return machineLabel(m);
  return (b && b.machine) ? b.machine.replace(/^[A-Z]+-\d+\s+/, '') : '';
}

// === Master data: Customers ==========================================
// Each customer has a list of contacts (each with phone) and a list of
// frequently-used job-site locations. Selecting a customer in Create
// Booking filters the contact dropdown to that customer's contacts; the
// linked phone auto-fills when a contact is selected.
const CUSTOMERS = [
  { id: 'C-001', name: 'Ace Engineering', jobs: 24, email: 'accounts@aceeng.com.my',
    contacts: [
      { name: 'Lim Wei Ming', phone: '+60 12-345 6789', email: 'wm.lim@aceeng.com.my' },
      { name: 'James Lim',    phone: '+60 12-988 1122', email: 'james@aceeng.com.my' },
    ],
    locations: ['Pasir Gudang Industrial Park, Lot 14B', 'PGI Phase 2', 'PGI Phase 3'],
  },
  { id: 'C-002', name: 'Greenword Sdn Bhd', jobs: 31, email: 'admin@greenword.com.my',
    contacts: [
      { name: 'Sarah Tan',   phone: '+60 13-887 2210', email: 'sarah.tan@greenword.com.my' },
      { name: 'Goh Wei Han', phone: '+60 12-664 7733', email: 'wh.goh@greenword.com.my' },
    ],
    locations: ['Medini Iskandar, Plot J-7', 'Medini Iskandar, Plot K-2'],
  },
  { id: 'C-003', name: 'QRE Logistics', jobs: 18, email: 'ops@qrelogistics.com',
    contacts: [
      { name: 'David Ng',     phone: '+60 17-223 4456', email: 'david.ng@qrelogistics.com' },
      { name: 'Sharon Yeoh',  phone: '+60 16-554 9988', email: 'sharon@qrelogistics.com' },
    ],
    locations: ['PTP Berth 8, container yard', 'PTP Berth 8 Yard'],
  },
  { id: 'C-004', name: 'DYC Aviation', jobs: 9, email: 'cargo@dycaviation.com',
    contacts: [
      { name: 'Aminah Yusof', phone: '+60 19-554 8821', email: 'aminah@dycaviation.com' },
    ],
    locations: ['Senai Airport Cargo Terminal 2', 'Senai Cargo Terminal 1'],
  },
  { id: 'C-005', name: 'KSB Builders', jobs: 14, email: 'projects@ksbbuilders.com.my',
    contacts: [
      { name: 'Tan Chee Keong', phone: '+60 12-998 7766', email: 'ck.tan@ksbbuilders.com.my' },
      { name: 'Lee Boon Hin',   phone: '+60 11-664 2299', email: 'bh.lee@ksbbuilders.com.my' },
    ],
    locations: ['Bukit Indah Phase 4, Block C', 'Bukit Indah Phase 4, Block D'],
  },
  { id: 'C-006', name: 'MTC Petrochem', jobs: 7, email: 'procurement@mtcpetrochem.com',
    contacts: [
      { name: 'Khairul Anwar', phone: '+60 13-445 9911', email: 'khairul@mtcpetrochem.com' },
    ],
    locations: ['Tanjung Langsat Terminal Bay 3'],
  },
  { id: 'C-007', name: 'JEC Industrial', jobs: 11, email: 'enquiry@jecindustrial.com.my',
    contacts: [
      { name: 'Vincent Lee', phone: '+60 14-552 2299', email: 'vincent.lee@jecindustrial.com.my' },
    ],
    locations: ['Kulai PLO 12, Lot 88', 'Kulai PLO 12, Lot 22', 'Kulai PLO 12, Lot 90'],
  },
];

// Global pool of all recurring site locations across customers
const LOCATIONS = [
  ...new Set(CUSTOMERS.flatMap(c => c.locations))
];

// === Customer price list ============================================
// Per-customer negotiated day-rates (RM) for every machine type Pow Lee
// hires out. Each row carries the CURRENT given price + the date it took
// effect, plus the PREVIOUS price and its date — so Account & Finance can
// see how a customer's rate has moved over time.
//
// PRICE_MACHINE_TYPES is the canonical priceable catalogue; the actual
// per-customer numbers are generated deterministically (seeded by
// customer + machine type) so they stay stable across renders.
const PRICE_MACHINE_TYPES = [
  { id: 'mc-20',  category: 'Mobile Crane',         spec: '20T',     base: 1200 },
  { id: 'mc-25',  category: 'Mobile Crane',         spec: '25T',     base: 1500 },
  { id: 'mc-45',  category: 'Mobile Crane',         spec: '45T',     base: 2400 },
  { id: 'mc-50',  category: 'Mobile Crane',         spec: '50T',     base: 2800 },
  { id: 'mc-120', category: 'Mobile Crane',         spec: '120T',    base: 6500 },
  { id: 'rt-25',  category: 'Rough Terrain Crane',  spec: '25T',     base: 1800 },
  { id: 'sl-20',  category: 'Skylift',              spec: '20M',     base:  700 },
  { id: 'sl-22',  category: 'Skylift',              spec: '22M',     base:  800 },
  { id: 'sl-24',  category: 'Skylift',              spec: '24M',     base:  900 },
  { id: 'sl-26',  category: 'Skylift',              spec: '26M',     base: 1000 },
  { id: 'sl-45',  category: 'Skylift',              spec: '45M',     base: 1800 },
  { id: 'scl',    category: 'Scissor Lift',         spec: 'GS-3246', base:  350 },
  { id: 'lc',     category: 'Lorry Crane',          spec: '10T',     base:  950 },
  { id: 'bl',     category: 'Boom Lift',            spec: '16M',     base: 1100 },
  { id: 'fl',     category: 'Forklift',             spec: '3T',      base:  600 },
];

// FNV-1a hash → stable unsigned int from a string seed
function _priceSeed(str) {
  let h = 2166136261;
  for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); }
  return h >>> 0;
}
const _round50 = (n) => Math.round(n / 50) * 50;
const _isoMinus = (iso, months) => {
  const d = new Date(iso + 'T12:00:00');
  d.setMonth(d.getMonth() - months);
  const y = d.getFullYear(), m = String(d.getMonth() + 1).padStart(2, '0'), dd = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${dd}`;
};

// Build the price rows for one customer.
function priceListFor(customerId) {
  return PRICE_MACHINE_TYPES.map(t => {
    const s = _priceSeed(customerId + '|' + t.id);
    // Negotiated factor 0.90–1.10 off the catalogue base
    const factor = 0.90 + (s % 21) / 100;
    const current = _round50(t.base * factor);
    // Whether the price changed at the last revision (≈75% did)
    const changed = (s % 4) !== 0;
    // Last revision was a 4–11% lower price (rates trend upward over time)
    const incrPct = 4 + (s % 8);
    const last = changed ? _round50(current / (1 + incrPct / 100)) : current;
    // Current price effective 1–10 months ago; previous 12–20 months before that
    const curMonthsAgo = 1 + (s % 10);
    const priceDate = _isoMinus(TODAY, curMonthsAgo);
    const lastDate = _isoMinus(priceDate, 12 + (s % 9));
    return {
      typeId: t.id,
      category: t.category,
      spec: t.spec,
      current,
      priceDate,
      last,
      lastDate,
      changed,
    };
  });
}

// === Operator certifications ========================================
// Short codes shown as coloured dots in the operator picker. The legend
// (code → label + colour) is rendered at the top of the dropdown so
// dispatch can read the dots at a glance while assigning a job.
const CERT_LEGEND = [
  { code: 'NTSP', label: 'NIOSH Tower Safety Passport', color: '#2563EB' },
  { code: 'OGSP', label: 'Oil & Gas Safety Passport',   color: '#0891B2' },
  { code: 'CIDB', label: 'CIDB Green Card',             color: '#059669' },
  { code: 'JKKP', label: 'JKKP / DOSH Competency (PMA)', color: '#D97706' },
  { code: 'H',    label: 'Class H — Heavy machinery',   color: '#7C3AED' },
  { code: 'E',    label: 'Class E — Heavy vehicle',     color: '#DC2626' },
  { code: 'D',    label: 'Class D — Car / light',       color: '#DB2777' },
  { code: 'B2',   label: 'Class B2 — Motorcycle',       color: '#0B1F3A' },
];
const CERT_COLOR = Object.fromEntries(CERT_LEGEND.map(c => [c.code, c.color]));
const CERT_LABEL = Object.fromEntries(CERT_LEGEND.map(c => [c.code, c.label]));

// === Master data: Operators (drivers) ================================
// Each cert now carries an expiry date (`exp`, ISO yyyy-mm-dd). Expired
// certs are hidden from the operator picker; certs expiring within
// CERT_RENEW_WINDOW_DAYS trigger a renewal reminder notification.
const OPERATORS = [
  { id: 'OP-01', name: 'Muthu',    phone: '+60 17-554 1188', license: 'OPL-A-2241', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-03-15'},{code:'JKKP',exp:'2026-07-20'},{code:'CIDB',exp:'2027-01-10'},{code:'H',exp:'2028-05-01'},{code:'E',exp:'2028-05-01'}] },
  { id: 'OP-02', name: 'Zorkapli', phone: '+60 12-998 7766', license: 'OPL-A-2198', status: 'Available', certs: [{code:'NTSP',exp:'2026-11-05'},{code:'CIDB',exp:'2027-06-12'},{code:'H',exp:'2029-02-20'},{code:'E',exp:'2029-02-20'}] },
  { id: 'OP-03', name: 'Zul30ton', phone: '+60 19-554 8821', license: 'OPL-A-2305', status: 'On Job',    certs: [{code:'NTSP',exp:'2026-06-28'},{code:'OGSP',exp:'2027-04-18'},{code:'JKKP',exp:'2027-09-30'},{code:'CIDB',exp:'2026-12-01'},{code:'H',exp:'2028-08-15'},{code:'E',exp:'2028-08-15'}] },
  { id: 'OP-04', name: 'Hairul',   phone: '+60 11-887 9911', license: 'OPL-A-2155', status: 'Available', certs: [{code:'NTSP',exp:'2027-02-14'},{code:'JKKP',exp:'2026-05-12'},{code:'H',exp:'2028-03-22'},{code:'E',exp:'2028-03-22'}] },
  { id: 'OP-05', name: 'Rajah',    phone: '+60 16-223 4456', license: 'OPL-A-2410', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-07-08'},{code:'CIDB',exp:'2027-03-19'},{code:'OGSP',exp:'2026-07-30'},{code:'H',exp:'2028-11-01'},{code:'E',exp:'2028-11-01'}] },
  { id: 'OP-06', name: 'Izzul',    phone: '+60 13-441 7782', license: 'OPL-A-2433', status: 'On Job',    certs: [{code:'NTSP',exp:'2028-01-25'},{code:'JKKP',exp:'2027-05-14'},{code:'CIDB',exp:'2027-08-09'},{code:'H',exp:'2029-04-12'},{code:'E',exp:'2029-04-12'},{code:'D',exp:'2030-06-30'}] },
  { id: 'OP-07', name: 'Teon',     phone: '+60 17-220 9914', license: 'OPL-A-2451', status: 'Available', certs: [{code:'NTSP',exp:'2027-10-03'},{code:'OGSP',exp:'2027-12-20'},{code:'JKKP',exp:'2026-07-11'},{code:'CIDB',exp:'2027-02-28'},{code:'H',exp:'2028-09-19'},{code:'E',exp:'2028-09-19'}] },
  { id: 'OP-08', name: 'Hisham',   phone: '+60 12-665 3320', license: 'OPL-A-2477', status: 'On Job',    certs: [{code:'NTSP',exp:'2026-04-22'},{code:'CIDB',exp:'2027-05-30'},{code:'H',exp:'2028-07-07'},{code:'E',exp:'2028-07-07'}] },
  { id: 'OP-09', name: 'Rohezal',  phone: '+60 19-883 1156', license: 'OPL-A-2489', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-06-15'},{code:'JKKP',exp:'2027-11-22'},{code:'H',exp:'2028-12-30'},{code:'E',exp:'2028-12-30'}] },
  { id: 'OP-10', name: 'Ganis',    phone: '+60 14-552 6610', license: 'OPL-A-2502', status: 'Available', certs: [{code:'NTSP',exp:'2027-09-01'},{code:'CIDB',exp:'2026-07-25'},{code:'H',exp:'2029-01-18'},{code:'E',exp:'2029-01-18'},{code:'D',exp:'2030-03-12'}] },
  { id: 'OP-11', name: 'Kanisan',  phone: '+60 16-770 4488', license: 'OPL-A-2518', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-04-09'},{code:'OGSP',exp:'2027-08-14'},{code:'CIDB',exp:'2027-12-05'},{code:'H',exp:'2028-10-22'},{code:'E',exp:'2028-10-22'}] },
  { id: 'OP-12', name: 'Selva',    phone: '+60 17-331 2299', license: 'OPL-A-2530', status: 'Available', certs: [{code:'NTSP',exp:'2027-01-30'},{code:'JKKP',exp:'2027-07-19'},{code:'H',exp:'2028-06-25'},{code:'E',exp:'2028-06-25'}] },
  { id: 'OP-13', name: 'Shafiq',   phone: '+60 11-225 8843', license: 'OPL-A-2547', status: 'Available', certs: [{code:'NTSP',exp:'2026-12-12'},{code:'CIDB',exp:'2027-03-08'},{code:'H',exp:'2028-08-30'},{code:'E',exp:'2028-08-30'}] },
  { id: 'OP-14', name: 'Yusof',    phone: '+60 13-558 1102', license: 'OPL-A-2561', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-05-20'},{code:'JKKP',exp:'2027-10-11'},{code:'CIDB',exp:'2027-06-28'},{code:'OGSP',exp:'2026-07-18'},{code:'H',exp:'2029-03-05'},{code:'E',exp:'2029-03-05'}] },
  { id: 'OP-15', name: 'Radzi',    phone: '+60 12-884 7790', license: 'OPL-A-2578', status: 'Available', certs: [{code:'NTSP',exp:'2027-08-22'},{code:'CIDB',exp:'2027-11-14'},{code:'H',exp:'2028-05-17'},{code:'E',exp:'2028-05-17'}] },
  { id: 'OP-16', name: 'Jembri',   phone: '+60 19-446 2218', license: 'OPL-S-3104', status: 'Available', certs: [{code:'NTSP',exp:'2027-02-26'},{code:'JKKP',exp:'2027-09-03'},{code:'H',exp:'2028-12-08'},{code:'D',exp:'2029-10-20'}] },
  { id: 'OP-17', name: 'Ahmad',    phone: '+60 17-882 5531', license: 'OPL-S-3122', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-07-30'},{code:'CIDB',exp:'2027-04-25'},{code:'H',exp:'2028-11-19'},{code:'D',exp:'2029-08-14'},{code:'B2',exp:'2030-01-09'}] },
  { id: 'OP-18', name: 'Hanapi',   phone: '+60 16-334 9907', license: 'OPL-S-3140', status: 'Available', certs: [{code:'NTSP',exp:'2026-07-05'},{code:'JKKP',exp:'2027-06-21'},{code:'H',exp:'2028-09-28'},{code:'D',exp:'2029-12-15'}] },
  { id: 'OP-19', name: 'Azizi',    phone: '+60 11-559 6643', license: 'OPL-S-3158', status: 'On Job',    certs: [{code:'NTSP',exp:'2027-03-11'},{code:'CIDB',exp:'2027-08-27'},{code:'H',exp:'2028-07-23'},{code:'D',exp:'2029-05-30'}] },
  { id: 'OP-20', name: 'Richard',  phone: '+60 14-221 7785', license: 'OPL-S-3171', status: 'Available', certs: [{code:'NTSP',exp:'2027-10-18'},{code:'OGSP',exp:'2027-05-09'},{code:'H',exp:'2028-10-04'},{code:'D',exp:'2029-09-22'},{code:'B2',exp:'2030-02-28'}] },
];

// === Certification expiry helpers ===================================
// Fixed "today" keeps the demo deterministic; swap for `new Date()` live.
const CERT_TODAY = new Date('2026-06-04');
const CERT_RENEW_WINDOW_DAYS = 60; // ~2 months — remind before a cert lapses
function certDaysLeft(iso, now = CERT_TODAY) {
  return Math.round((new Date(iso + 'T00:00:00') - now) / 86400000);
}
function certState(iso, now = CERT_TODAY) {
  const left = certDaysLeft(iso, now);
  if (left < 0) return 'expired';
  if (left <= CERT_RENEW_WINDOW_DAYS) return 'expiring';
  return 'valid';
}
// Certs fit to show — expired ones are dropped entirely.
function activeCerts(certs, now = CERT_TODAY) {
  return (certs || []).filter(c => certState(c.exp, now) !== 'expired');
}
function fmtCertDate(iso) {
  if (!iso) return '—';
  return new Date(iso + 'T00:00:00').toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}
// Flat, soonest-first list of renewals due (expiring) or overdue (expired)
// across all operators — feeds the renewal reminders in Notifications.
function certReminders(operators = OPERATORS, now = CERT_TODAY) {
  const out = [];
  operators.forEach(o => (o.certs || []).forEach(c => {
    const state = certState(c.exp, now);
    if (state === 'expiring' || state === 'expired') {
      out.push({ operator: o.name, opId: o.id, code: c.code, label: CERT_LABEL[c.code] || c.code, exp: c.exp, days: certDaysLeft(c.exp, now), state });
    }
  }));
  return out.sort((a, b) => a.days - b.days);
}

const RIGGERS = [
  { id: 'RG-01', name: 'Ahmad Faizal',   phone: '+60 13-445 9911', cert: 'NIOSH-RG-1102', status: 'On Job' },
  { id: 'RG-02', name: 'Subash Kumar',   phone: '+60 14-552 2299', cert: 'NIOSH-RG-1105', status: 'On Job' },
  { id: 'RG-03', name: 'Bala Krishnan',  phone: '+60 17-223 4456', cert: 'NIOSH-RG-1108', status: 'Available' },
  { id: 'RG-04', name: 'Pravin Raj',     phone: '+60 12-887 2210', cert: 'NIOSH-RG-1112', status: 'On Job' },
];

// === Master data: Site Tools / Equipment ============================
// Admin-managed list of accessories an operator may need to bring on site.
// Surfaced in Create Booking as a multi-select; managed from Administration → Tools.
const TOOLS = [
  { id: 'T-01', name: 'Outrigger Pads (steel)',  category: 'Stability',  default: true  },
  { id: 'T-02', name: 'Outrigger Pads (timber)', category: 'Stability',  default: false },
  { id: 'T-03', name: 'Spreader Bar — 2t',       category: 'Rigging',    default: false },
  { id: 'T-04', name: 'Spreader Bar — 5t',       category: 'Rigging',    default: false },
  { id: 'T-05', name: 'Wire Sling — 3m',         category: 'Rigging',    default: false },
  { id: 'T-06', name: 'Wire Sling — 6m',         category: 'Rigging',    default: false },
  { id: 'T-07', name: 'Chain Block — 1t',        category: 'Rigging',    default: false },
  { id: 'T-08', name: 'Bow Shackle 17t',         category: 'Rigging',    default: false },
  { id: 'T-09', name: 'Wheel Chocks',            category: 'Safety',     default: true  },
  { id: 'T-10', name: 'Safety Cones (10×)',      category: 'Safety',     default: true  },
  { id: 'T-11', name: 'Barrier Tape Roll',       category: 'Safety',     default: false },
  { id: 'T-12', name: 'Spotter Radio (pair)',    category: 'Comms',      default: false },
  { id: 'T-13', name: 'Diesel Jerry Can 20L',    category: 'Fuel',       default: false },
];

// === Shift options ===================================================
// Three only — locked by user requirement
const SHIFT_OPTIONS = [
  { id: 'fullday',   label: '8am – 5pm',   start: '08:00', end: '17:00' },
  { id: 'morning',   label: '8am – 12pm',  start: '08:00', end: '12:00' },
  { id: 'afternoon', label: '1pm – 5pm',   start: '13:00', end: '17:00' },
  { id: 'custom',    label: 'Custom Time', start: '',      end: ''      },
];

// === Dynamic "today" anchored to Malaysia time (UTC+8) ==============
// The demo data was authored around ANCHOR_DATE. We compute the real current
// date in Asia/Kuala_Lumpur (GMT+8, no DST) and shift every booking date by the
// same offset — so "Today" in Current Bookings is ALWAYS the real Malaysia day
// while the yesterday/today/tomorrow demo structure is preserved.
const ANCHOR_DATE = '2026-04-29';
function klTodayISO() {
  const now = new Date();
  // Shift the UTC instant to UTC+8, then read its calendar date.
  const kl = new Date(now.getTime() + (now.getTimezoneOffset() + 480) * 60000);
  const y = kl.getFullYear();
  const m = String(kl.getMonth() + 1).padStart(2, '0');
  const d = String(kl.getDate()).padStart(2, '0');
  return `${y}-${m}-${d}`;
}
function isoFromLocal(d) {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
function addDaysISO(iso, n) {
  if (!iso) return iso;
  const d = new Date(iso + 'T00:00:00');
  d.setDate(d.getDate() + n);
  return isoFromLocal(d);
}
function daysBetweenISO(a, b) {
  return Math.round((new Date(b + 'T00:00:00') - new Date(a + 'T00:00:00')) / 86400000);
}
const TODAY = klTodayISO();
const DATE_SHIFT = daysBetweenISO(ANCHOR_DATE, TODAY);

// === Bookings (formerly Work Orders) =================================
// Today = 2026-04-29, so we have yesterday/today/tomorrow/day-after data.
const BOOKINGS = [
  // YESTERDAY 2026-04-28
  { id: 'BK-2026-00418', customer: 'KSB Builders', contact: 'Tan Chee Keong', phone: '+60 12-998 7766', location: 'Bukit Indah Phase 4, Block C', machine: 'PLC-005 Tadano GR-500EX', plate: '9744', category: 'Mobile Crane', tonnage: '50t', date: '2026-04-28', shift: 'morning', start: '08:00', end: '12:00', operator: 'Yong Ah Seng', rigger: 'Bala Krishnan', desc: 'Erect tower crane mast sections.', price: 'RM 5,200', diesel: 'RM 360', remarks: '', status: 'Job Completed', urgency: 'normal' },
  { id: 'BK-2026-00419', customer: 'JEC Industrial', contact: 'Vincent Lee', phone: '+60 14-552 2299', location: 'Kulai PLO 12, Lot 88', machine: 'PLC-003 Tadano GR-300EX', plate: '7838', category: 'Mobile Crane', tonnage: '30t', date: '2026-04-28', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Mohd Hafiz', rigger: 'Pravin Raj', desc: 'Steel structure delivery and offload.', price: 'RM 3,200', diesel: 'RM 210', remarks: '', status: 'Cancelled', urgency: 'normal' },
  { id: 'BK-2026-00417', customer: 'Ace Engineering', contact: 'Lim Wei Ming', phone: '+60 12-345 6789', location: 'Pasir Gudang Industrial Park, Lot 14B', machine: 'PLC-016 Genie S-65', plate: '5936', category: 'Skylift', tonnage: '20m', date: '2026-04-28', shift: 'morning', start: '08:00', end: '12:00', operator: 'Razak Hassan', rigger: '—', desc: 'Façade inspection and bolt-tightening at height.', price: 'RM 1,400', diesel: 'RM 80', remarks: '', status: 'Job Completed', urgency: 'normal' },

  // TODAY 2026-04-29 — these match the AppSheet view (multiple bookings, mixed categories)
  { id: 'BK-2026-00420', customer: 'Ace Engineering', contact: 'Lim Wei Ming', phone: '+60 12-345 6789', location: 'Pasir Gudang Industrial Park, Lot 14B', machine: 'PLC-005 Tadano GR-500EX', plate: '9744', category: 'Mobile Crane', tonnage: '50t', date: '2026-04-29', shift: 'custom', start: '08:00', end: '17:00', operator: 'Gopal Raju', rigger: 'Ahmad Faizal', desc: 'Lift and place 4× pre-cast columns onto foundation. Site has tight access via north gate.', price: 'RM 4,800', diesel: 'RM 320', remarks: 'Bring outrigger pads — soft ground', status: 'On the Way', urgency: 'normal' },
  { id: 'BK-2026-00421', customer: 'Greenword Sdn Bhd', contact: 'Sarah Tan', phone: '+60 13-887 2210', location: 'Medini Iskandar, Plot J-7', machine: 'PLC-009 Liebherr LTM 1090', plate: '8569', category: 'Mobile Crane', tonnage: '90t', date: '2026-04-29', shift: 'custom', start: '07:00', end: '19:00', operator: 'Chong Kah Hoe', rigger: 'Subash Kumar', desc: 'Lift HVAC units to rooftop, 12 floors. JKR permit required.', price: 'RM 8,500', diesel: 'RM 540', remarks: 'JKR officer onsite from 9am', status: 'Job Started', urgency: 'urgent' },
  { id: 'BK-2026-00422', customer: 'QRE Logistics', contact: 'David Ng', phone: '+60 17-223 4456', location: 'PTP Berth 8, container yard', machine: 'PLC-011 Grove GMK4100L', plate: '5114', category: 'Mobile Crane', tonnage: '100t', date: '2026-04-29', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Mohd Hafiz', rigger: 'Pravin Raj', desc: 'Container handling — 12 reefers from quay to staging.', price: 'RM 6,200', diesel: 'RM 420', remarks: 'Night work, lighting required', status: 'Assigned', urgency: 'normal' },
  { id: 'BK-2026-00423', customer: 'KSB Builders', contact: 'Tan Chee Keong', phone: '+60 12-998 7766', location: 'Bukit Indah Phase 4, Block C', machine: 'PLC-014 Liebherr LTM 1200', plate: '239', category: 'Mobile Crane', tonnage: '200t', date: '2026-04-29', shift: 'morning', start: '08:00', end: '12:00', operator: 'Yong Ah Seng', rigger: 'Bala Krishnan', desc: 'Heavy lift — pre-cast bridge girder.', price: 'RM 12,000', diesel: 'RM 800', remarks: '', status: 'Accepted', urgency: 'normal' },
  { id: 'BK-2026-00424', customer: 'Ace Engineering', contact: 'Lim Wei Ming', phone: '+60 12-345 6789', location: 'PGI Phase 2', machine: 'PLC-017 JLG 600S', plate: '9437', category: 'Skylift', tonnage: '20m', date: '2026-04-29', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Razak Hassan', rigger: '—', desc: 'High-bay lighting installation.', price: 'RM 1,200', diesel: 'RM 70', remarks: '', status: 'On the Way', urgency: 'normal' },
  { id: 'BK-2026-00425', customer: 'Greenword Sdn Bhd', contact: 'Sarah Tan', phone: '+60 13-887 2210', location: 'Medini Iskandar, Plot J-7', machine: 'PLC-019 Aichi SK22A', plate: '2122', category: 'Skylift', tonnage: '22m', date: '2026-04-29', shift: 'custom', start: '09:00', end: '18:00', operator: 'Suresh', rigger: '—', desc: 'Internal ceiling fit-out.', price: 'RM 850', diesel: 'RM 40', remarks: '', status: 'Assigned', urgency: 'normal' },
  { id: 'BK-2026-00426', customer: 'QRE Logistics', contact: 'David Ng', phone: '+60 17-223 4456', location: 'PTP Berth 8 Yard', machine: 'PLC-008 Kobelco RK700', plate: '8908', category: 'Mobile Crane', tonnage: '70t', date: '2026-04-29', shift: 'morning', start: '08:00', end: '12:00', operator: 'Mohd Hafiz', rigger: 'Pravin Raj', desc: 'Container fittings delivery.', price: 'RM 1,800', diesel: 'RM 120', remarks: '', status: 'Accepted', urgency: 'normal' },
  { id: 'BK-2026-00433', customer: 'DYC Aviation', contact: 'Aminah Yusof', phone: '+60 19-554 8821', location: 'Senai Cargo Terminal 1', machine: 'PLC-001 Tadano GR-250N', plate: '8382', category: 'Mobile Crane', tonnage: '25t', date: '2026-04-29', shift: 'morning', start: '08:00', end: '12:00', operator: 'Razak Hassan', rigger: '—', desc: 'Small parcel lift — generator swap.', price: 'RM 2,200', diesel: 'RM 150', remarks: '', status: 'Job Started', urgency: 'normal' },
  { id: 'BK-2026-00434', customer: 'JEC Industrial', contact: 'Vincent Lee', phone: '+60 14-552 2299', location: 'Kulai PLO 12, Lot 22', machine: 'PLC-006 Tadano GR-500EX', plate: '4758', category: 'Mobile Crane', tonnage: '50t', date: '2026-04-29', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Yong Ah Seng', rigger: 'Bala Krishnan', desc: 'Equipment relocation — 3 lifts.', price: 'RM 3,800', diesel: 'RM 240', remarks: '', status: 'Assigned', urgency: 'normal' },

  // TOMORROW 2026-04-30
  { id: 'BK-2026-00427', customer: 'DYC Aviation', contact: 'Aminah Yusof', phone: '+60 19-554 8821', location: 'Senai Airport Cargo Terminal 2', machine: 'PLC-001 Tadano GR-250N', plate: '8382', category: 'Mobile Crane', tonnage: '25t', date: '2026-04-30', shift: 'morning', start: '08:00', end: '12:00', operator: 'Razak Hassan', rigger: '—', desc: 'Generator placement on warehouse roof.', price: 'RM 2,400', diesel: 'RM 180', remarks: '', status: 'Accepted', urgency: 'normal' },
  { id: 'BK-2026-00428', customer: 'MTC Petrochem', contact: 'Khairul Anwar', phone: '+60 13-445 9911', location: 'Tanjung Langsat Terminal Bay 3', machine: 'PLC-015 Liebherr LTM 1250', plate: '3135', category: 'Mobile Crane', tonnage: '250t', date: '2026-04-30', shift: 'custom', start: '05:00', end: '20:00', operator: 'Chong Kah Hoe', rigger: 'Subash Kumar', desc: 'Storage tank dome installation. Hazardous area — hot work permit.', price: 'RM 18,500', diesel: 'RM 1,200', remarks: 'Confined permits issued', status: 'Pending Issue', urgency: 'urgent' },
  { id: 'BK-2026-00429', customer: 'Greenword Sdn Bhd', contact: 'Sarah Tan', phone: '+60 13-887 2210', location: 'Medini Iskandar, Plot K-2', machine: 'PLC-013 Tadano ATF 130G-5', plate: '284', category: 'Mobile Crane', tonnage: '130t', date: '2026-04-30', shift: 'morning', start: '08:00', end: '12:00', operator: 'Yong Ah Seng', rigger: 'Bala Krishnan', desc: 'Tower crane top-out support lift.', price: 'RM 9,400', diesel: 'RM 620', remarks: '', status: 'Assigned', urgency: 'normal' },
  { id: 'BK-2026-00430', customer: 'KSB Builders', contact: 'Tan Chee Keong', phone: '+60 12-998 7766', location: 'Bukit Indah Phase 4, Block D', machine: 'PLC-018 Genie Z-80/60', plate: '328', category: 'Skylift', tonnage: '24m', date: '2026-04-30', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Suresh', rigger: '—', desc: 'External cladding inspection.', price: 'RM 1,400', diesel: 'RM 80', remarks: '', status: 'Assigned', urgency: 'normal' },

  // DAY AFTER TOMORROW 2026-05-01
  { id: 'BK-2026-00431', customer: 'Ace Engineering', contact: 'Lim Wei Ming', phone: '+60 12-345 6789', location: 'PGI Phase 3', machine: 'PLC-007 Tadano GR-500EX', plate: '9552', category: 'Mobile Crane', tonnage: '50t', date: '2026-05-01', shift: 'morning', start: '08:00', end: '12:00', operator: 'Mohd Hafiz', rigger: 'Pravin Raj', desc: 'Pre-fab beam erection.', price: 'RM 4,800', diesel: 'RM 320', remarks: '', status: 'Assigned', urgency: 'normal' },
  { id: 'BK-2026-00432', customer: 'JEC Industrial', contact: 'Vincent Lee', phone: '+60 14-552 2299', location: 'Kulai PLO 12, Lot 90', machine: 'PLC-020 Snorkel TB42', plate: '9418', category: 'Skylift', tonnage: '14m', date: '2026-05-01', shift: 'custom', start: '07:00', end: '15:00', operator: 'Suresh', rigger: '—', desc: 'Building maintenance — sign installation.', price: 'RM 1,200', diesel: 'RM 80', remarks: '', status: 'Assigned', urgency: 'normal' },

  // +3 DAYS 2026-05-02
  { id: 'BK-2026-00435', customer: 'MTC Petrochem', contact: 'Khairul Anwar', phone: '+60 13-445 9911', location: 'Tanjung Langsat Terminal Bay 3', machine: 'PLC-003 Tadano GR-300EX', plate: '7838', category: 'Mobile Crane', tonnage: '120t', date: '2026-05-02', shift: 'custom', start: '07:00', end: '18:00', operator: 'Mohd Hafiz', rigger: 'Subash Kumar', desc: 'Pipe rack module lift — phased over the day.', price: 'RM 9,800', diesel: 'RM 640', remarks: 'Hot work permit pending', status: 'Assigned', urgency: 'normal' },
  { id: 'BK-2026-00436', customer: 'Ace Engineering', contact: 'Lim Wei Ming', phone: '+60 12-345 6789', location: 'PGI Phase 2', machine: 'PLC-009 Liebherr LTM 1090', plate: '8569', category: 'Mobile Crane', tonnage: '90t', date: '2026-05-02', shift: 'morning', start: '08:00', end: '12:00', operator: 'Chong Kah Hoe', rigger: 'Bala Krishnan', desc: 'Chiller unit lift to rooftop plant room.', price: 'RM 7,200', diesel: 'RM 480', remarks: '', status: 'Accepted', urgency: 'normal' },
  { id: 'BK-2026-00437', customer: 'KSB Builders', contact: 'Tan Chee Keong', phone: '+60 12-998 7766', location: 'Bukit Indah Phase 4, Block D', machine: 'PLC-016 Genie S-65', plate: '5936', category: 'Skylift', tonnage: '20m', date: '2026-05-02', shift: 'afternoon', start: '13:00', end: '17:00', operator: 'Razak Hassan', rigger: '—', desc: 'Façade glazing inspection at height.', price: 'RM 1,300', diesel: 'RM 80', remarks: '', status: 'Assigned', urgency: 'normal' },

  // === Historical backfill (auto-generated for All Bookings demo) ===
  {"id":"BK-2025-00500","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"Sutera Utama","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2025-01-01","dateFrom":"2025-01-01","dateTo":"2025-01-01","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Hanapi","rigger":"Bala Krishnan","desc":"Booking","price":"RM 658","diesel":"RM 496","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00501","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-006 (see master)","plate":"4758","category":"Mobile Crane","tonnage":"50t","date":"2025-01-03","dateFrom":"2025-01-03","dateTo":"2025-01-03","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Jembri","rigger":"Pravin Raj","desc":"Booking","price":"RM 4,106","diesel":"RM 349","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00502","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Sutera Utama","machine":"PLC-002 (see master)","plate":"6382","category":"Mobile Crane","tonnage":"25t","date":"2025-01-14","dateFrom":"2025-01-14","dateTo":"2025-01-14","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Razak Hassan","rigger":"—","desc":"Booking","price":"RM 2,925","diesel":"RM 393","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00503","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"Pmu Cahaya","machine":"PLC-005 (see master)","plate":"9744","category":"Mobile Crane","tonnage":"50t","date":"2025-01-01","dateFrom":"2025-01-01","dateTo":"2025-01-01","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"Bala Krishnan","desc":"Booking","price":"RM 1,751","diesel":"RM 607","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00504","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"Taman Johor","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-02-21","dateFrom":"2025-02-21","dateTo":"2025-02-21","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"—","desc":"Booking","price":"RM 6,346","diesel":"RM 362","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00505","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"PTP Berth 8 Yard","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2025-02-11","dateFrom":"2025-02-11","dateTo":"2025-02-11","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Suresh","rigger":"—","desc":"Booking","price":"RM 7,469","diesel":"RM 155","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00506","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"Desa Terbau","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-02-12","dateFrom":"2025-02-12","dateTo":"2025-02-12","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Richard","rigger":"—","desc":"Booking","price":"RM 3,646","diesel":"RM 549","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00507","customer":"Ame Const","contact":"Kana M","phone":"+60 17-883 1188","location":"silc lot 7","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2025-02-15","dateFrom":"2025-02-15","dateTo":"2025-02-15","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 5,799","diesel":"RM 117","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00508","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Desa Terbau","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2025-02-25","dateFrom":"2025-02-25","dateTo":"2025-02-27","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"—","desc":"Booking","price":"RM 3,827","diesel":"RM 515","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00508","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Desa Terbau","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2025-02-26","dateFrom":"2025-02-25","dateTo":"2025-02-27","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"—","desc":"Booking","price":"RM 3,827","diesel":"RM 515","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00508","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Desa Terbau","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2025-02-27","dateFrom":"2025-02-25","dateTo":"2025-02-27","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"—","desc":"Booking","price":"RM 3,827","diesel":"RM 515","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00509","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"Tanjung Langsat","machine":"PLC-004 (see master)","plate":"1484","category":"Mobile Crane","tonnage":"30t","date":"2025-03-23","dateFrom":"2025-03-23","dateTo":"2025-03-23","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"Bala Krishnan","desc":"Booking","price":"RM 9,299","diesel":"RM 52","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00510","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Pmu Cahaya","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2025-03-01","dateFrom":"2025-03-01","dateTo":"2025-03-01","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Subash Kumar","desc":"Booking","price":"RM 8,427","diesel":"RM 160","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00511","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Seelong","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2025-03-19","dateFrom":"2025-03-19","dateTo":"2025-03-19","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Subash Kumar","desc":"Booking","price":"RM 3,662","diesel":"RM 262","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00512","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"JB Bandar","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-03-12","dateFrom":"2025-03-12","dateTo":"2025-03-15","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 5,470","diesel":"RM 432","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00512","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"JB Bandar","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-03-13","dateFrom":"2025-03-12","dateTo":"2025-03-15","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 5,470","diesel":"RM 432","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00512","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"JB Bandar","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-03-14","dateFrom":"2025-03-12","dateTo":"2025-03-15","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 5,470","diesel":"RM 432","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00512","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"JB Bandar","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-03-15","dateFrom":"2025-03-12","dateTo":"2025-03-15","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 5,470","diesel":"RM 432","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00513","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Bukit Indah Phase 4","machine":"PLC-002 (see master)","plate":"6382","category":"Mobile Crane","tonnage":"25t","date":"2025-04-18","dateFrom":"2025-04-18","dateTo":"2025-04-18","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Hanapi","rigger":"—","desc":"Booking","price":"RM 1,189","diesel":"RM 574","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00514","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"silc lot 7","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-04-28","dateFrom":"2025-04-28","dateTo":"2025-04-30","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 416","diesel":"RM 248","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00514","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"silc lot 7","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-04-29","dateFrom":"2025-04-28","dateTo":"2025-04-30","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 416","diesel":"RM 248","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00514","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"silc lot 7","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-04-30","dateFrom":"2025-04-28","dateTo":"2025-04-30","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 416","diesel":"RM 248","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00515","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pmu Cahaya","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2025-04-12","dateFrom":"2025-04-12","dateTo":"2025-04-12","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 981","diesel":"RM 213","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00516","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Kulai PLO 12, Lot 88","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-04-09","dateFrom":"2025-04-09","dateTo":"2025-04-09","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Bala Krishnan","desc":"Booking","price":"RM 1,142","diesel":"RM 195","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00517","customer":"DYC Aviation","contact":"Aminah Yusof","phone":"+60 19-554 8821","location":"Pontian","machine":"PLC-009 (see master)","plate":"8569","category":"Mobile Crane","tonnage":"90t","date":"2025-04-27","dateFrom":"2025-04-27","dateTo":"2025-04-27","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Mohd Hafiz","rigger":"Bala Krishnan","desc":"Booking","price":"RM 7,998","diesel":"RM 237","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00518","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai","machine":"CR-005 Cross Rent 5","plate":"CR-5","category":"Cross Rent","tonnage":"150t","date":"2025-05-30","dateFrom":"2025-05-30","dateTo":"2025-06-02","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"","rigger":"—","desc":"Booking","price":"RM 3,797","diesel":"RM 550","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00518","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai","machine":"CR-005 Cross Rent 5","plate":"CR-5","category":"Cross Rent","tonnage":"150t","date":"2025-05-31","dateFrom":"2025-05-30","dateTo":"2025-06-02","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"","rigger":"—","desc":"Booking","price":"RM 3,797","diesel":"RM 550","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00518","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai","machine":"CR-005 Cross Rent 5","plate":"CR-5","category":"Cross Rent","tonnage":"150t","date":"2025-06-01","dateFrom":"2025-05-30","dateTo":"2025-06-02","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"","rigger":"—","desc":"Booking","price":"RM 3,797","diesel":"RM 550","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00518","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai","machine":"CR-005 Cross Rent 5","plate":"CR-5","category":"Cross Rent","tonnage":"150t","date":"2025-06-02","dateFrom":"2025-05-30","dateTo":"2025-06-02","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"","rigger":"—","desc":"Booking","price":"RM 3,797","diesel":"RM 550","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00519","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"Taman Johor","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2025-05-26","dateFrom":"2025-05-26","dateTo":"2025-05-26","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Richard","rigger":"—","desc":"Booking","price":"RM 6,407","diesel":"RM 80","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00520","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"JB Bandar","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2025-05-04","dateFrom":"2025-05-04","dateTo":"2025-05-04","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"Pravin Raj","desc":"Booking","price":"RM 1,919","diesel":"RM 389","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00521","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Senai","machine":"PLC-011 (see master)","plate":"5114","category":"Mobile Crane","tonnage":"100t","date":"2025-05-11","dateFrom":"2025-05-11","dateTo":"2025-05-11","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Suresh","rigger":"Pravin Raj","desc":"Booking","price":"RM 6,828","diesel":"RM 138","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00522","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2025-05-12","dateFrom":"2025-05-12","dateTo":"2025-05-12","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Yong Ah Seng","rigger":"Subash Kumar","desc":"Booking","price":"RM 7,523","diesel":"RM 568","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00523","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Desa Terbau","machine":"CR-001 Cross Rent 1","plate":"CR-1","category":"Cross Rent","tonnage":"25t","date":"2025-06-27","dateFrom":"2025-06-27","dateTo":"2025-06-27","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"","rigger":"—","desc":"Booking","price":"RM 4,973","diesel":"RM 220","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00524","customer":"Ace Engineering","contact":"Lim Wei Ming","phone":"+60 12-345 6789","location":"Taman Johor","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-06-11","dateFrom":"2025-06-11","dateTo":"2025-06-11","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yusof","rigger":"Subash Kumar","desc":"Booking","price":"RM 2,120","diesel":"RM 515","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00525","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"silc lot 7","machine":"PLC-011 (see master)","plate":"5114","category":"Mobile Crane","tonnage":"100t","date":"2025-06-06","dateFrom":"2025-06-06","dateTo":"2025-06-06","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 1,089","diesel":"RM 333","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00526","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Medini Iskandar, Plot J-7","machine":"PLC-013 (see master)","plate":"284","category":"Mobile Crane","tonnage":"130t","date":"2025-06-07","dateFrom":"2025-06-07","dateTo":"2025-06-07","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Kanisan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 2,278","diesel":"RM 299","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00527","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"Senai Cargo Terminal 1","machine":"CR-003 Cross Rent 3","plate":"CR-3","category":"Cross Rent","tonnage":"90t","date":"2025-07-27","dateFrom":"2025-07-27","dateTo":"2025-07-27","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"","rigger":"—","desc":"Booking","price":"RM 2,868","diesel":"RM 545","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00528","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"Senai Airport Cargo","machine":"PLC-020 (see master)","plate":"9418","category":"Skylift","tonnage":"14m","date":"2025-07-16","dateFrom":"2025-07-16","dateTo":"2025-07-16","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"—","desc":"Booking","price":"RM 4,368","diesel":"RM 564","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00529","customer":"Pamir","contact":"Liyana A","phone":"+60 16-227 5577","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-009 (see master)","plate":"8569","category":"Mobile Crane","tonnage":"90t","date":"2025-07-21","dateFrom":"2025-07-21","dateTo":"2025-07-21","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Razak Hassan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 638","diesel":"RM 459","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00530","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Senai Airport Cargo","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-07-21","dateFrom":"2025-07-21","dateTo":"2025-07-21","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Hanapi","rigger":"—","desc":"Booking","price":"RM 6,173","diesel":"RM 85","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00531","customer":"DYC Aviation","contact":"Aminah Yusof","phone":"+60 19-554 8821","location":"Senai Cargo Terminal 1","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2025-07-06","dateFrom":"2025-07-06","dateTo":"2025-07-06","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"Subash Kumar","desc":"Booking","price":"RM 7,345","diesel":"RM 330","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00532","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"PGI Phase 3","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2025-07-01","dateFrom":"2025-07-01","dateTo":"2025-07-01","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Hanapi","rigger":"Pravin Raj","desc":"Booking","price":"RM 2,744","diesel":"RM 478","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00533","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Bukit Indah Phase 4","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-08-28","dateFrom":"2025-08-28","dateTo":"2025-08-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"Pravin Raj","desc":"Booking","price":"RM 5,985","diesel":"RM 167","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00533","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Bukit Indah Phase 4","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-08-29","dateFrom":"2025-08-28","dateTo":"2025-08-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"Pravin Raj","desc":"Booking","price":"RM 5,985","diesel":"RM 167","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00533","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Bukit Indah Phase 4","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-08-30","dateFrom":"2025-08-28","dateTo":"2025-08-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"Pravin Raj","desc":"Booking","price":"RM 5,985","diesel":"RM 167","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00533","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Bukit Indah Phase 4","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-08-31","dateFrom":"2025-08-28","dateTo":"2025-08-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Mohd Hafiz","rigger":"Pravin Raj","desc":"Booking","price":"RM 5,985","diesel":"RM 167","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00534","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Senai Airport Cargo","machine":"PLC-006 (see master)","plate":"4758","category":"Mobile Crane","tonnage":"50t","date":"2025-08-12","dateFrom":"2025-08-12","dateTo":"2025-08-12","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"Bala Krishnan","desc":"Booking","price":"RM 8,585","diesel":"RM 238","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00535","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"Sutera Utama","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2025-08-08","dateFrom":"2025-08-08","dateTo":"2025-08-08","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Razak Hassan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 5,932","diesel":"RM 216","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00536","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"CR-003 Cross Rent 3","plate":"CR-3","category":"Cross Rent","tonnage":"90t","date":"2025-08-14","dateFrom":"2025-08-14","dateTo":"2025-08-14","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"","rigger":"—","desc":"Booking","price":"RM 2,133","diesel":"RM 191","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00537","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Tanjung Langsat","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2025-08-18","dateFrom":"2025-08-18","dateTo":"2025-08-18","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"Pravin Raj","desc":"Booking","price":"RM 2,881","diesel":"RM 83","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00538","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-010 (see master)","plate":"4368","category":"Mobile Crane","tonnage":"90t","date":"2025-09-23","dateFrom":"2025-09-23","dateTo":"2025-09-23","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Subash Kumar","desc":"Booking","price":"RM 6,512","diesel":"RM 71","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00539","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"PTP Berth 8 Yard","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-09-30","dateFrom":"2025-09-30","dateTo":"2025-10-03","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 7,514","diesel":"RM 492","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00539","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"PTP Berth 8 Yard","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-10-01","dateFrom":"2025-09-30","dateTo":"2025-10-03","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 7,514","diesel":"RM 492","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00539","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"PTP Berth 8 Yard","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-10-02","dateFrom":"2025-09-30","dateTo":"2025-10-03","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 7,514","diesel":"RM 492","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00539","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"PTP Berth 8 Yard","machine":"PLC-001 (see master)","plate":"8382","category":"Mobile Crane","tonnage":"25t","date":"2025-10-03","dateFrom":"2025-09-30","dateTo":"2025-10-03","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 7,514","diesel":"RM 492","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00540","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Desa Terbau","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-09-03","dateFrom":"2025-09-03","dateTo":"2025-09-07","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,859","diesel":"RM 301","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00540","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Desa Terbau","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-09-04","dateFrom":"2025-09-03","dateTo":"2025-09-07","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,859","diesel":"RM 301","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00540","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Desa Terbau","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-09-05","dateFrom":"2025-09-03","dateTo":"2025-09-07","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,859","diesel":"RM 301","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00540","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Desa Terbau","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-09-06","dateFrom":"2025-09-03","dateTo":"2025-09-07","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,859","diesel":"RM 301","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00540","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Desa Terbau","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-09-07","dateFrom":"2025-09-03","dateTo":"2025-09-07","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,859","diesel":"RM 301","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00541","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Taman Johor","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2025-09-02","dateFrom":"2025-09-02","dateTo":"2025-09-02","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"Bala Krishnan","desc":"Booking","price":"RM 2,857","diesel":"RM 154","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00542","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"Tanjung Langsat Terminal Bay 3","machine":"CR-002 Cross Rent 2","plate":"CR-2","category":"Cross Rent","tonnage":"50t","date":"2025-09-18","dateFrom":"2025-09-18","dateTo":"2025-09-18","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 1,344","diesel":"RM 486","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00543","customer":"Greenword Sdn Bhd","contact":"Sarah Tan","phone":"+60 13-887 2210","location":"PGI Phase 3","machine":"CR-003 Cross Rent 3","plate":"CR-3","category":"Cross Rent","tonnage":"90t","date":"2025-09-29","dateFrom":"2025-09-29","dateTo":"2025-09-29","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"","rigger":"—","desc":"Booking","price":"RM 6,140","diesel":"RM 556","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00544","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"PGI Phase 3","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2025-09-06","dateFrom":"2025-09-06","dateTo":"2025-09-06","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"Pravin Raj","desc":"Booking","price":"RM 7,110","diesel":"RM 270","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00545","customer":"Ame Const","contact":"Kana M","phone":"+60 17-883 1188","location":"Seelong","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2025-10-28","dateFrom":"2025-10-28","dateTo":"2025-10-28","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Razak Hassan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 7,291","diesel":"RM 555","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00546","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Senai","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2025-10-24","dateFrom":"2025-10-24","dateTo":"2025-10-24","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 7,934","diesel":"RM 144","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00547","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"Seelong","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-29","dateFrom":"2025-10-29","dateTo":"2025-10-29","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Rajah","rigger":"—","desc":"Booking","price":"RM 3,138","diesel":"RM 442","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00548","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"Tanjung Langsat","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2025-10-15","dateFrom":"2025-10-15","dateTo":"2025-10-15","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 9,157","diesel":"RM 555","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00549","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Desa Terbau","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2025-10-15","dateFrom":"2025-10-15","dateTo":"2025-10-15","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Rajah","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 8,127","diesel":"RM 142","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00550","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai Airport Cargo","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-27","dateFrom":"2025-10-27","dateTo":"2025-10-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"—","desc":"Booking","price":"RM 2,886","diesel":"RM 405","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00550","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai Airport Cargo","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-28","dateFrom":"2025-10-27","dateTo":"2025-10-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"—","desc":"Booking","price":"RM 2,886","diesel":"RM 405","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00550","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai Airport Cargo","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-29","dateFrom":"2025-10-27","dateTo":"2025-10-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"—","desc":"Booking","price":"RM 2,886","diesel":"RM 405","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00550","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai Airport Cargo","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-30","dateFrom":"2025-10-27","dateTo":"2025-10-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"—","desc":"Booking","price":"RM 2,886","diesel":"RM 405","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00550","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Senai Airport Cargo","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2025-10-31","dateFrom":"2025-10-27","dateTo":"2025-10-31","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Muthu","rigger":"—","desc":"Booking","price":"RM 2,886","diesel":"RM 405","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00551","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Senai Cargo Terminal 1","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2025-11-24","dateFrom":"2025-11-24","dateTo":"2025-11-24","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Richard","rigger":"Bala Krishnan","desc":"Booking","price":"RM 4,222","diesel":"RM 617","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00552","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"JB Bandar","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2025-11-03","dateFrom":"2025-11-03","dateTo":"2025-11-03","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 6,240","diesel":"RM 373","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00553","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2025-11-21","dateFrom":"2025-11-21","dateTo":"2025-11-21","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Subash Kumar","desc":"Booking","price":"RM 6,898","diesel":"RM 236","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00554","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Senai Airport Cargo","machine":"PLC-006 (see master)","plate":"4758","category":"Mobile Crane","tonnage":"50t","date":"2025-11-18","dateFrom":"2025-11-18","dateTo":"2025-11-18","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 1,532","diesel":"RM 484","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00555","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"JB Bandar","machine":"PLC-002 (see master)","plate":"6382","category":"Mobile Crane","tonnage":"25t","date":"2025-12-29","dateFrom":"2025-12-29","dateTo":"2025-12-29","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"—","desc":"Booking","price":"RM 5,046","diesel":"RM 274","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00556","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Pontian","machine":"CR-006 Cross Rent 6","plate":"CR-6","category":"Cross Rent","tonnage":"20m","date":"2025-12-21","dateFrom":"2025-12-21","dateTo":"2025-12-23","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 6,266","diesel":"RM 476","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00556","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Pontian","machine":"CR-006 Cross Rent 6","plate":"CR-6","category":"Cross Rent","tonnage":"20m","date":"2025-12-22","dateFrom":"2025-12-21","dateTo":"2025-12-23","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 6,266","diesel":"RM 476","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00556","customer":"Turbopak","contact":"Tony Yusof","phone":"+60 11-553 4477","location":"Pontian","machine":"CR-006 Cross Rent 6","plate":"CR-6","category":"Cross Rent","tonnage":"20m","date":"2025-12-23","dateFrom":"2025-12-21","dateTo":"2025-12-23","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 6,266","diesel":"RM 476","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00557","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Taman Johor","machine":"PLC-020 (see master)","plate":"9418","category":"Skylift","tonnage":"14m","date":"2025-12-28","dateFrom":"2025-12-28","dateTo":"2025-12-28","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Yusof","rigger":"—","desc":"Booking","price":"RM 4,745","diesel":"RM 554","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00558","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Seelong","machine":"PLC-002 (see master)","plate":"6382","category":"Mobile Crane","tonnage":"25t","date":"2025-12-23","dateFrom":"2025-12-23","dateTo":"2025-12-23","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"—","desc":"Booking","price":"RM 1,762","diesel":"RM 438","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2025-00559","customer":"Ace Engineering","contact":"Lim Wei Ming","phone":"+60 12-345 6789","location":"Taman Johor","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2025-12-19","dateFrom":"2025-12-19","dateTo":"2025-12-19","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yong Ah Seng","rigger":"—","desc":"Booking","price":"RM 6,934","diesel":"RM 507","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00560","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Senai","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2026-01-31","dateFrom":"2026-01-31","dateTo":"2026-02-02","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Bala Krishnan","desc":"Booking","price":"RM 6,269","diesel":"RM 50","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00560","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Senai","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2026-02-01","dateFrom":"2026-01-31","dateTo":"2026-02-02","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Bala Krishnan","desc":"Booking","price":"RM 6,269","diesel":"RM 50","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00560","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Senai","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2026-02-02","dateFrom":"2026-01-31","dateTo":"2026-02-02","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Bala Krishnan","desc":"Booking","price":"RM 6,269","diesel":"RM 50","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00561","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-01-12","dateFrom":"2026-01-12","dateTo":"2026-01-12","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Suresh","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 1,983","diesel":"RM 161","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00562","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"Pmu Cahaya","machine":"PLC-010 (see master)","plate":"4368","category":"Mobile Crane","tonnage":"90t","date":"2026-01-28","dateFrom":"2026-01-28","dateTo":"2026-01-29","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Hanapi","rigger":"Subash Kumar","desc":"Booking","price":"RM 2,940","diesel":"RM 500","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00562","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"Pmu Cahaya","machine":"PLC-010 (see master)","plate":"4368","category":"Mobile Crane","tonnage":"90t","date":"2026-01-29","dateFrom":"2026-01-28","dateTo":"2026-01-29","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Hanapi","rigger":"Subash Kumar","desc":"Booking","price":"RM 2,940","diesel":"RM 500","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00563","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"PGI Phase 3","machine":"PLC-005 (see master)","plate":"9744","category":"Mobile Crane","tonnage":"50t","date":"2026-01-31","dateFrom":"2026-01-31","dateTo":"2026-01-31","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Subash Kumar","desc":"Booking","price":"RM 8,313","diesel":"RM 613","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00564","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Bukit Indah Phase 4","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2026-01-18","dateFrom":"2026-01-18","dateTo":"2026-01-18","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Subash Kumar","desc":"Booking","price":"RM 7,785","diesel":"RM 226","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00565","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Pontian","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-02-13","dateFrom":"2026-02-13","dateTo":"2026-02-16","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Muthu","rigger":"Bala Krishnan","desc":"Booking","price":"RM 5,399","diesel":"RM 513","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00565","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Pontian","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-02-14","dateFrom":"2026-02-13","dateTo":"2026-02-16","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Muthu","rigger":"Bala Krishnan","desc":"Booking","price":"RM 5,399","diesel":"RM 513","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00565","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Pontian","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-02-15","dateFrom":"2026-02-13","dateTo":"2026-02-16","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Muthu","rigger":"Bala Krishnan","desc":"Booking","price":"RM 5,399","diesel":"RM 513","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00565","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Pontian","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-02-16","dateFrom":"2026-02-13","dateTo":"2026-02-16","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Muthu","rigger":"Bala Krishnan","desc":"Booking","price":"RM 5,399","diesel":"RM 513","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00566","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Tanjung Langsat","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2026-02-22","dateFrom":"2026-02-22","dateTo":"2026-02-25","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 3,537","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00566","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Tanjung Langsat","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2026-02-23","dateFrom":"2026-02-22","dateTo":"2026-02-25","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 3,537","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00566","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Tanjung Langsat","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2026-02-24","dateFrom":"2026-02-22","dateTo":"2026-02-25","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 3,537","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00566","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Tanjung Langsat","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2026-02-25","dateFrom":"2026-02-22","dateTo":"2026-02-25","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 3,537","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00567","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"JB Bandar","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2026-02-27","dateFrom":"2026-02-27","dateTo":"2026-02-27","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 526","diesel":"RM 478","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00568","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Tanjung Langsat Terminal Bay 3","machine":"CR-006 Cross Rent 6","plate":"CR-6","category":"Cross Rent","tonnage":"20m","date":"2026-02-08","dateFrom":"2026-02-08","dateTo":"2026-02-08","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 6,837","diesel":"RM 54","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00569","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"Senai Cargo Terminal 1","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-02-22","dateFrom":"2026-02-22","dateTo":"2026-02-22","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Yusof","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 1,499","diesel":"RM 210","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00570","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2026-02-08","dateFrom":"2026-02-08","dateTo":"2026-02-09","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Razak Hassan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 4,788","diesel":"RM 66","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00570","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2026-02-09","dateFrom":"2026-02-08","dateTo":"2026-02-09","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Razak Hassan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 4,788","diesel":"RM 66","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00571","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"PTP Berth 8 Yard","machine":"PLC-003 (see master)","plate":"7838","category":"Mobile Crane","tonnage":"30t","date":"2026-02-21","dateFrom":"2026-02-21","dateTo":"2026-02-21","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"Bala Krishnan","desc":"Booking","price":"RM 4,566","diesel":"RM 60","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00572","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"Sutera Utama","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2026-03-06","dateFrom":"2026-03-06","dateTo":"2026-03-06","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Razak Hassan","rigger":"—","desc":"Booking","price":"RM 2,888","diesel":"RM 385","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00573","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-03-29","dateFrom":"2026-03-29","dateTo":"2026-04-02","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 2,077","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00573","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-03-30","dateFrom":"2026-03-29","dateTo":"2026-04-02","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 2,077","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00573","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-03-31","dateFrom":"2026-03-29","dateTo":"2026-04-02","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 2,077","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00573","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-04-01","dateFrom":"2026-03-29","dateTo":"2026-04-02","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 2,077","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00573","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-04-02","dateFrom":"2026-03-29","dateTo":"2026-04-02","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 2,077","diesel":"RM 480","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00574","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Seelong","machine":"PLC-019 (see master)","plate":"2122","category":"Skylift","tonnage":"22m","date":"2026-03-10","dateFrom":"2026-03-10","dateTo":"2026-03-10","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Jembri","rigger":"—","desc":"Booking","price":"RM 823","diesel":"RM 356","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00575","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"JB Bandar","machine":"PLC-004 (see master)","plate":"1484","category":"Mobile Crane","tonnage":"30t","date":"2026-03-28","dateFrom":"2026-03-28","dateTo":"2026-03-28","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Richard","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 1,354","diesel":"RM 349","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00576","customer":"MTC Petrochem","contact":"Khairul Anwar","phone":"+60 13-445 9911","location":"PGI Phase 3","machine":"PLC-011 (see master)","plate":"5114","category":"Mobile Crane","tonnage":"100t","date":"2026-03-12","dateFrom":"2026-03-12","dateTo":"2026-03-12","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Hanapi","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 3,516","diesel":"RM 391","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00577","customer":"Jay brother","contact":"Jay Lim","phone":"+60 12-554 6611","location":"Senai Cargo Terminal 1","machine":"PLC-020 (see master)","plate":"9418","category":"Skylift","tonnage":"14m","date":"2026-04-14","dateFrom":"2026-04-14","dateTo":"2026-04-14","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"—","desc":"Booking","price":"RM 3,997","diesel":"RM 165","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00578","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2026-04-02","dateFrom":"2026-04-02","dateTo":"2026-04-05","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Suresh","rigger":"—","desc":"Booking","price":"RM 6,498","diesel":"RM 235","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00578","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2026-04-03","dateFrom":"2026-04-02","dateTo":"2026-04-05","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Suresh","rigger":"—","desc":"Booking","price":"RM 6,498","diesel":"RM 235","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00578","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2026-04-04","dateFrom":"2026-04-02","dateTo":"2026-04-05","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Suresh","rigger":"—","desc":"Booking","price":"RM 6,498","diesel":"RM 235","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00578","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Medini Iskandar, Plot J-7","machine":"PLC-018 (see master)","plate":"328","category":"Skylift","tonnage":"24m","date":"2026-04-05","dateFrom":"2026-04-02","dateTo":"2026-04-05","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Suresh","rigger":"—","desc":"Booking","price":"RM 6,498","diesel":"RM 235","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00579","customer":"Pamir","contact":"Liyana A","phone":"+60 16-227 5577","location":"Medini Iskandar, Plot J-7","machine":"PLC-012 (see master)","plate":"8172","category":"Mobile Crane","tonnage":"100t","date":"2026-04-28","dateFrom":"2026-04-28","dateTo":"2026-04-28","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Chong Kah Hoe","rigger":"Subash Kumar","desc":"Booking","price":"RM 4,837","diesel":"RM 165","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00580","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Bukit Indah Phase 4","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2026-04-23","dateFrom":"2026-04-23","dateTo":"2026-04-25","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 531","diesel":"RM 389","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00580","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Bukit Indah Phase 4","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2026-04-24","dateFrom":"2026-04-23","dateTo":"2026-04-25","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 531","diesel":"RM 389","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00580","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Bukit Indah Phase 4","machine":"PLC-014 (see master)","plate":"239","category":"Mobile Crane","tonnage":"200t","date":"2026-04-25","dateFrom":"2026-04-23","dateTo":"2026-04-25","multi":true,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 531","diesel":"RM 389","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00581","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Tanjung Langsat","machine":"CR-006 Cross Rent 6","plate":"CR-6","category":"Cross Rent","tonnage":"20m","date":"2026-04-10","dateFrom":"2026-04-10","dateTo":"2026-04-10","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"","rigger":"—","desc":"Booking","price":"RM 3,812","diesel":"RM 190","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00582","customer":"Egosky Steels sb","contact":"Aziz Mohamed","phone":"+60 13-661 3322","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2026-04-13","dateFrom":"2026-04-13","dateTo":"2026-04-13","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Razak Hassan","rigger":"—","desc":"Booking","price":"RM 868","diesel":"RM 266","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00583","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Medini Iskandar, Plot J-7","machine":"PLC-009 (see master)","plate":"8569","category":"Mobile Crane","tonnage":"90t","date":"2026-04-09","dateFrom":"2026-04-09","dateTo":"2026-04-09","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Pravin Raj","desc":"Booking","price":"RM 5,377","diesel":"RM 288","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00584","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"JB Bandar","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-05-15","dateFrom":"2026-05-15","dateTo":"2026-05-15","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Richard","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 3,924","diesel":"RM 99","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00585","customer":"Pamir","contact":"Liyana A","phone":"+60 16-227 5577","location":"JB Bandar","machine":"PLC-004 (see master)","plate":"1484","category":"Mobile Crane","tonnage":"30t","date":"2026-05-01","dateFrom":"2026-05-01","dateTo":"2026-05-01","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 8,158","diesel":"RM 463","remarks":"Bring outrigger pads","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00586","customer":"LKS Green","contact":"Wei Lim","phone":"+60 18-225 9911","location":"Pontian","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-05-08","dateFrom":"2026-05-08","dateTo":"2026-05-08","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Yusof","rigger":"Bala Krishnan","desc":"Booking","price":"RM 3,139","diesel":"RM 309","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00587","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"JB Bandar","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2026-05-31","dateFrom":"2026-05-31","dateTo":"2026-06-01","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Hanapi","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 4,395","diesel":"RM 176","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00587","customer":"JEC Industrial","contact":"Vincent Lee","phone":"+60 14-552 2299","location":"JB Bandar","machine":"PLC-015 (see master)","plate":"3135","category":"Mobile Crane","tonnage":"250t","date":"2026-06-01","dateFrom":"2026-05-31","dateTo":"2026-06-01","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Hanapi","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 4,395","diesel":"RM 176","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00588","customer":"DYC Aviation","contact":"Aminah Yusof","phone":"+60 19-554 8821","location":"Tanjung Langsat Terminal Bay 3","machine":"PLC-004 (see master)","plate":"1484","category":"Mobile Crane","tonnage":"30t","date":"2026-05-21","dateFrom":"2026-05-21","dateTo":"2026-05-21","multi":false,"shift":"morning","start":"08:00","end":"12:00","operator":"Jembri","rigger":"Bala Krishnan","desc":"Booking","price":"RM 2,569","diesel":"RM 243","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00589","customer":"Transgreen","contact":"Sara Choo","phone":"+60 19-445 8821","location":"Pmu Cahaya","machine":"PLC-009 (see master)","plate":"8569","category":"Mobile Crane","tonnage":"90t","date":"2026-05-26","dateFrom":"2026-05-26","dateTo":"2026-05-26","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Kanisan","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 1,841","diesel":"RM 87","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00590","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"silc lot 7","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-05-10","dateFrom":"2026-05-10","dateTo":"2026-05-12","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 2,190","diesel":"RM 96","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00590","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"silc lot 7","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-05-11","dateFrom":"2026-05-10","dateTo":"2026-05-12","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 2,190","diesel":"RM 96","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00590","customer":"KSB Builders","contact":"Tan Chee Keong","phone":"+60 12-998 7766","location":"silc lot 7","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-05-12","dateFrom":"2026-05-10","dateTo":"2026-05-12","multi":true,"shift":"custom","start":"07:00","end":"18:00","operator":"Yong Ah Seng","rigger":"Pravin Raj","desc":"Booking","price":"RM 2,190","diesel":"RM 96","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00591","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Seelong","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-06-21","dateFrom":"2026-06-21","dateTo":"2026-06-22","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Muthu","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 9,097","diesel":"RM 57","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00591","customer":"QRE Logistics","contact":"David Ng","phone":"+60 17-223 4456","location":"Seelong","machine":"PLC-008 (see master)","plate":"8908","category":"Mobile Crane","tonnage":"70t","date":"2026-06-22","dateFrom":"2026-06-21","dateTo":"2026-06-22","multi":true,"shift":"morning","start":"08:00","end":"12:00","operator":"Muthu","rigger":"Ahmad Faizal","desc":"Booking","price":"RM 9,097","diesel":"RM 57","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00592","customer":"QUANTUM RENEWABLE ENERGY","contact":"Mr Tan","phone":"+60 19-991 2233","location":"Kulai PLO 12, Lot 88","machine":"PLC-016 (see master)","plate":"5936","category":"Skylift","tonnage":"20m","date":"2026-06-08","dateFrom":"2026-06-08","dateTo":"2026-06-08","multi":false,"shift":"afternoon","start":"13:00","end":"17:00","operator":"Mohd Hafiz","rigger":"—","desc":"Booking","price":"RM 4,636","diesel":"RM 282","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00593","customer":"Ace Engineering","contact":"Lim Wei Ming","phone":"+60 12-345 6789","location":"Pontian","machine":"CR-002 Cross Rent 2","plate":"CR-2","category":"Cross Rent","tonnage":"50t","date":"2026-06-15","dateFrom":"2026-06-15","dateTo":"2026-06-15","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"","rigger":"—","desc":"Booking","price":"RM 8,542","diesel":"RM 101","remarks":"","status":"Job Completed","urgency":"normal"},
  {"id":"BK-2026-00594","customer":"Easyfast","contact":"Jenny Wong","phone":"+60 12-770 4455","location":"Pontian","machine":"PLC-007 (see master)","plate":"9552","category":"Mobile Crane","tonnage":"50t","date":"2026-06-18","dateFrom":"2026-06-18","dateTo":"2026-06-18","multi":false,"shift":"custom","start":"07:00","end":"18:00","operator":"Hanapi","rigger":"Subash Kumar","desc":"Booking","price":"RM 5,164","diesel":"RM 509","remarks":"","status":"Job Completed","urgency":"normal"},
];

// Roll every booking date forward to the live calendar so the demo's
// yesterday/today/tomorrow buckets always align with the real Malaysia date.
if (DATE_SHIFT !== 0) {
  BOOKINGS.forEach(b => {
    b.date = addDaysISO(b.date, DATE_SHIFT);
    if (b.dateFrom) b.dateFrom = addDaysISO(b.dateFrom, DATE_SHIFT);
    if (b.dateTo) b.dateTo = addDaysISO(b.dateTo, DATE_SHIFT);
  });
}

// Backwards compat for existing pages still reading WORK_ORDERS
const WORK_ORDERS = BOOKINGS.map(b => ({
  ...b, crane: b.machine, duration: b.shift === 'custom' ? 'Custom' : (b.shift === 'morning' ? 'Half Day AM' : 'Half Day PM')
}));

const STATUS_MAP = {
  'Assigned':       { color: 'gray',   label: 'Assigned' },
  'Accepted':       { color: 'blue',   label: 'Accepted' },
  'On the Way':     { color: 'purple', label: 'On the Way' },
  'Arrived Site':   { color: 'yellow', label: 'Arrived Site' },
  'Job Started':    { color: 'orange', label: 'Job Started' },
  'Job Completed':  { color: 'green',  label: 'Completed' },
  'Pending Issue':  { color: 'red',    label: 'Pending Issue' },
  'Cancelled':      { color: 'gray',   label: 'Cancelled' },
};

// === Daily ops notes (Admin + Operation only) ========================
// Freeform per-day standup log — direct port from AppSheet "Notes"
const DAILY_NOTES = [
  { date: '2026-04-29', author: 'Sarah Tan',  text: 'Ahmad Shafiq absence — back at 9.30am. Irwan to ride 6382 with Razak. JKR officer arriving 9am Medini site.' },
  { date: '2026-04-28', author: 'Sarah Tan',  text: 'Heavy rain forecast PM — Bukit Indah job moved to morning shift only. Cancelled Kulai job at 11am — chargeable per terms.' },
  { date: '2026-04-27', author: 'Wei Ming Lim', text: 'PLC-006 returned from workshop — back in fleet. PLC-013 still in for boom inspection until Friday.' },
  { date: '2026-04-26', author: 'Sarah Tan',  text: 'New customer onboarded — DYC Aviation, contact Aminah. Rate card sent.' },
  { date: '2026-04-25', author: 'Wei Ming Lim', text: 'Diesel surcharge updated to RM 0.45/L effective today (was RM 0.40/L). All quotes after 25/4 use new rate.' },
].map(n => ({ ...n, date: addDaysISO(n.date, DATE_SHIFT) }));

const NOTIFICATIONS = [
  { id: 1, type: 'job', title: 'Tomorrow\'s Schedule Released', msg: 'Your jobs for 30 April are now available. 1 booking — 8:00 AM at Senai Airport with Rigger Ahmad Faizal.', time: '7:00 PM', unread: true, kind: 'info' },
  { id: 2, type: 'urgent', title: 'Tomorrow\'s Job Changed', msg: 'BK-2026-00427 — start time moved from 6:00 AM to 8:00 AM. Customer rescheduled after 7pm cut-off. Please confirm.', time: '9 min ago', unread: true, kind: 'urgent' },
  { id: 3, type: 'change', title: 'Job Location Changed', msg: 'BK-2026-00422 — new gate access via Berth 7, not Berth 8. Re-route operator.', time: '1 hr ago', unread: true, kind: 'info' },
  { id: 4, type: 'job', title: 'New Booking Assigned', msg: '50 Ton Crane, Pasir Gudang, 29 April 2026, 8:00 AM. Customer: Ace Engineering.', time: '3 hr ago', unread: false, kind: 'info' },
  { id: 5, type: 'mechanic', title: 'Repair Ticket Assigned', msg: 'Liebherr LTM 1090 (PLC-003) — hydraulic leak. Mechanic Awei assigned, priority high.', time: 'Yesterday', unread: false, kind: 'urgent' },
  { id: 6, type: 'approval', title: 'Approval Request', msg: 'Quote for MTC Petrochem (RM 18,500) awaiting management sign-off.', time: 'Yesterday', unread: false, kind: 'info' },
  { id: 7, type: 'cancel', title: 'Job Cancelled', msg: 'BK-2026-00419 — JEC Industrial cancelled by customer. Diesel + travel still chargeable.', time: '2 days ago', unread: false, kind: 'success' },
];

// === R&M ============================================================
// Repair = unscheduled fault tickets; Maintenance = recurring schedule.
// Maintenance days_left can be negative (overdue).
const REPAIR_TICKETS = [
  { id: 'RT-0142', machine: 'JFR 4368 (20T)', issue: 'Hydraulic line leak — boom cylinder', priority: 'High', mechanic: 'Awei', parts: 'Hydraulic seal kit, 2L ATF', supplier: 'Hydratek JB', cost: 'RM 1,840', status: 'In Progress', remarks: '', opened: '2026-04-27' },
  { id: 'RT-0141', machine: 'JGA 9744 (20T)', issue: 'Slew gear noise on left rotation', priority: 'Medium', mechanic: 'Sathya', parts: 'Slew bearing grease, gasket', supplier: 'Komatsu JB', cost: 'RM 620', status: 'Awaiting Parts', remarks: 'Gear inspection clear — lubrication issue', opened: '2026-04-26' },
  { id: 'RT-0140', machine: 'JEM 5114 (20T)', issue: 'Outrigger jack drift on rear-left', priority: 'High', mechanic: 'Awei', parts: 'Check valve, hydraulic hose', supplier: 'Grove SEA', cost: 'RM 2,200', status: 'Completed', remarks: 'Replaced check valve, system pressure-tested OK.', opened: '2026-04-22' },
  { id: 'RT-0139', machine: 'JSB 8382 (50T)', issue: 'Engine warning light — DEF system', priority: 'Low', mechanic: 'Melon', parts: 'DEF fluid 10L', supplier: 'Tadano SC', cost: 'RM 95', status: 'Completed', remarks: 'Topped up, sensor reset.', opened: '2026-04-19' },
  { id: 'RT-0138', machine: 'BRS 3135 (7T)', issue: 'Boom inspection annual — pending parts', priority: 'Medium', mechanic: 'Sathya', parts: 'Inspection seal kit', supplier: 'Liebherr SEA', cost: 'RM 1,250', status: 'In Progress', remarks: 'Annual NIOSH inspection in progress', opened: '2026-04-21' },
];

// === Regular maintenance: FIXED service catalog =====================
// Each recurring item has a FIXED countdown period, expressed in MONTHS.
// These are the standard service intervals applied to every mobile crane.
// Editing here changes the interval everywhere the item is scheduled.
const SERVICE_ITEMS = [
  { item: 'Engine Oil',                 months: 3  },
  { item: 'Gear Oil',                   months: 6  },
  { item: 'Steering Oil',               months: 6  },
  { item: 'Back Gear Oil',              months: 12 },
  { item: 'Swing Oil',                  months: 6  },
  { item: 'Hydraulic Filter (2 units)', months: 6  },
  { item: 'Hydraulic Oil (M)',          months: 60 },
  { item: 'Oberon Grease',              months: 12 },
  { item: 'Chain Sling 1',              months: 36 },
  { item: 'Chain Sling 2',              months: 36 },
];

// Quick lookup: service item name -> fixed interval in months
const SERVICE_INTERVAL_MONTHS = SERVICE_ITEMS.reduce((acc, s) => { acc[s.item] = s.months; return acc; }, {});

// Workshop dropdown sources for R&M (new ticket / add schedule)
const MECHANICS = ['Awei', 'Sathya', 'Melon'];
const SUPPLIERS = [
  'Hydratek JB',
  'Komatsu JB',
  'Grove SEA',
  'Tadano SC',
  'Liebherr SEA',
  'Hap Seng Trucks',
  'JB Hydraulics & Oil',
  'Southern Parts Supply',
];

// === Supplier directory (Master Data › Supplier) =====================
// Richer records than the SUPPLIERS dropdown list above — these drive the
// Supplier master table. `name` matches the dropdown strings so R&M tickets
// and these records reconcile.
const SUPPLIER_DIRECTORY = [
  { id: 'SUP-01', name: 'Hydratek JB',          category: 'Hydraulics',   contact: 'Mr. Tan C.K.',   phone: '+60 7-238 4471', email: 'sales@hydratek.com.my',  terms: '30 days',   status: 'Active' },
  { id: 'SUP-02', name: 'Komatsu JB',           category: 'OEM Parts',    contact: 'Ms. Faridah',    phone: '+60 7-557 9920', email: 'parts@komatsu-jb.com',   terms: '45 days',   status: 'Active' },
  { id: 'SUP-03', name: 'Grove SEA',            category: 'OEM Parts',    contact: 'David Lim',      phone: '+65 6863 2200',  email: 'support@grovesea.com',  terms: '60 days',   status: 'Active' },
  { id: 'SUP-04', name: 'Tadano SC',            category: 'OEM Parts',    contact: 'Ken Yamada',     phone: '+65 6265 1188',  email: 'parts@tadano.com.sg',   terms: '60 days',   status: 'Active' },
  { id: 'SUP-05', name: 'Liebherr SEA',         category: 'OEM Parts',    contact: 'Anna Wahid',     phone: '+65 6418 1000',  email: 'service@liebherr.sg',   terms: '60 days',   status: 'Active' },
  { id: 'SUP-06', name: 'Hap Seng Trucks',      category: 'Tyres & Trucks', contact: 'Mr. Goh',      phone: '+60 7-861 2233', email: 'jb@hapsengtrucks.com',  terms: '30 days',   status: 'Active' },
  { id: 'SUP-07', name: 'JB Hydraulics & Oil',  category: 'Lubricants',   contact: 'Rahman Aziz',    phone: '+60 7-334 8810', email: 'order@jbhydoil.my',     terms: '14 days',   status: 'Active' },
  { id: 'SUP-08', name: 'Southern Parts Supply', category: 'Consumables', contact: 'Lim Siew Hong',  phone: '+60 7-552 1047', email: 'sps@southernparts.my',  terms: '30 days',   status: 'On hold' },
];

// === Parts & consumables inventory (Master Data › Stocks) ============
// Workshop store stock. `qty` vs `reorder` drives the low-stock flag.
const STOCKS = [
  { id: 'STK-001', item: 'Hydraulic seal kit (boom cylinder)', sku: 'HSK-20T',   category: 'Hydraulics',  qty: 6,   unit: 'kit',    reorder: 4,  location: 'Rack A-2', supplier: 'Hydratek JB' },
  { id: 'STK-002', item: 'ATF hydraulic oil',                  sku: 'ATF-208L',  category: 'Lubricants',  qty: 3,   unit: 'drum',   reorder: 2,  location: 'Bay B',   supplier: 'JB Hydraulics & Oil' },
  { id: 'STK-003', item: 'Slew bearing grease',                sku: 'GRS-EP2',   category: 'Lubricants',  qty: 18,  unit: 'tube',   reorder: 10, location: 'Rack A-1', supplier: 'JB Hydraulics & Oil' },
  { id: 'STK-004', item: 'Engine oil filter',                  sku: 'FLT-OIL',   category: 'Filters',     qty: 2,   unit: 'pc',     reorder: 6,  location: 'Rack C-3', supplier: 'Komatsu JB' },
  { id: 'STK-005', item: 'Fuel filter element',                sku: 'FLT-FUEL',  category: 'Filters',     qty: 9,   unit: 'pc',     reorder: 6,  location: 'Rack C-3', supplier: 'Komatsu JB' },
  { id: 'STK-006', item: 'DEF fluid (AdBlue)',                 sku: 'DEF-10L',   category: 'Consumables', qty: 12,  unit: 'jug',    reorder: 8,  location: 'Bay B',   supplier: 'Tadano SC' },
  { id: 'STK-007', item: 'Wire rope 16mm',                     sku: 'WR-16',     category: 'Rigging',     qty: 120, unit: 'm',      reorder: 60, location: 'Yard',    supplier: 'Southern Parts Supply' },
  { id: 'STK-008', item: 'Bow shackle 8.5T',                   sku: 'SHK-85',    category: 'Rigging',     qty: 5,   unit: 'pc',     reorder: 12, location: 'Rack D-1', supplier: 'Southern Parts Supply' },
  { id: 'STK-009', item: 'Webbing sling 5T x 4m',              sku: 'SLG-5T4',   category: 'Rigging',     qty: 22,  unit: 'pc',     reorder: 10, location: 'Rack D-2', supplier: 'Southern Parts Supply' },
  { id: 'STK-010', item: 'Outrigger check valve',             sku: 'CV-OR',     category: 'Hydraulics',  qty: 1,   unit: 'pc',     reorder: 3,  location: 'Rack A-2', supplier: 'Grove SEA' },
  { id: 'STK-011', item: 'Brake pad set',                      sku: 'BRK-PAD',   category: 'Consumables', qty: 7,   unit: 'set',    reorder: 4,  location: 'Rack C-1', supplier: 'Hap Seng Trucks' },
  { id: 'STK-012', item: 'Tyre 14.00-24 (rough terrain)',      sku: 'TYR-1424',  category: 'Tyres',       qty: 4,   unit: 'pc',     reorder: 4,  location: 'Yard',    supplier: 'Hap Seng Trucks' },
];

// === Maintenance schedule (generated from the fixed catalog) =========
// Each tracked crane carries the full service checklist above. last/next are
// derived from the fixed interval; days_left counts down to next service.
const MAINTENANCE = (function buildMaintenance() {
  const TODAY_D = new Date(TODAY + 'T00:00:00');
  const DAY = 86400000;
  // Deterministic pseudo-random so the demo spread is stable across reloads.
  let seed = 1337;
  const rnd = () => { seed = (seed * 1103515245 + 12345) & 0x7fffffff; return seed / 0x7fffffff; };
  const addMonths = (d, m) => { const x = new Date(d); x.setMonth(x.getMonth() + m); return x; };
  const fmt = (d) => isoFromLocal(d);

  // Tracked cranes — use the real fleet labels from MACHINES.
  const trackedIds = ['PLC-001', 'PLC-003', 'PLC-005', 'PLC-007', 'PLC-009', 'PLC-011'];
  const label = (id) => { const m = MACHINES.find(x => x.id === id); return m ? machineLabel(m) : id; };

  const rows = [];
  let n = 1;
  trackedIds.forEach((id) => {
    SERVICE_ITEMS.forEach((s) => {
      const intervalDays = Math.round(s.months * 30.44);
      // Where in its cycle is this item? Short-interval items (engine/oils) are
      // allowed to slip overdue; long-interval items (chain slings, hyd oil M)
      // sit comfortably mid-cycle.
      const lo = s.months <= 6 ? -0.22 : 0.05;
      const frac = lo + rnd() * (1 - lo);
      const daysLeft = Math.round(frac * intervalDays);
      const next = new Date(TODAY_D.getTime() + daysLeft * DAY);
      const last = addMonths(next, -s.months);
      rows.push({
        id: 'MT-' + String(n++).padStart(3, '0'),
        machine: label(id),
        type: s.item,
        months: s.months,
        interval_days: intervalDays,
        days_left: daysLeft,
        last: fmt(last),
        next: fmt(next),
      });
    });
  });
  return rows;
})();

const ROLES = ['Admin', 'Operation', 'Operator', 'Rigger', 'Mechanic', 'Finance', 'Management'];

// === Role-Based Access Control ======================================
// 'view' = read-only · 'edit' = view + create/edit · 'none' = hidden
// Special rules layered on top in pages:
//   - Bookings: only Admin can CREATE; only Management can DELETE
//   - Customers: only Admin can ADD/EDIT
//   - Notes: only Admin + Operation can VIEW
const PERMISSIONS = {
  dashboard:     { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'view', Management: 'view' },
  allbookings:   { Admin: 'edit', Operation: 'edit', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'view', Management: 'edit' },
  bookings:      { Admin: 'edit', Operation: 'edit', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'view', Management: 'edit' }, // Mgmt edit = delete authority
  create:        { Admin: 'edit', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'none', Management: 'none' }, // Admin ONLY
  notes:         { Admin: 'edit', Operation: 'edit', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'none', Management: 'none' }, // Admin + Op only
  mobile:        { Admin: 'view', Operation: 'view', Operator: 'edit', Rigger: 'edit', Mechanic: 'none', Finance: 'none', Management: 'none' },
  completion:    { Admin: 'view', Operation: 'view', Operator: 'edit', Rigger: 'view', Mechanic: 'none', Finance: 'view', Management: 'view' },
  notifications: { Admin: 'edit', Operation: 'edit', Operator: 'view', Rigger: 'view', Mechanic: 'view', Finance: 'view', Management: 'view' },
  rm:            { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'edit', Finance: 'none', Management: 'view' },
  rmitems:       { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'view', Finance: 'view', Management: 'view' }, // Master Data — only Admin can add/edit
  analytics:     { Admin: 'edit', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'view', Management: 'edit' },
  export:        { Admin: 'edit', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'edit', Management: 'view' },
  pricelist:     { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'edit', Management: 'view' }, // Master Data › Customer
  masterdata:    { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'view', Finance: 'view', Management: 'view' }, // Machinery — only Admin can add/edit
  employees:     { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'view', Finance: 'view', Management: 'view' },
  stocks:        { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'edit', Finance: 'view', Management: 'view' },
  suppliers:     { Admin: 'edit', Operation: 'view', Operator: 'none', Rigger: 'none', Mechanic: 'view', Finance: 'edit', Management: 'view' },
  tools:         { Admin: 'edit', Operation: 'view', Operator: 'view', Rigger: 'view', Mechanic: 'view', Finance: 'none', Management: 'view' },
  users:         { Admin: 'edit', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'none', Management: 'none' },
  settings:      { Admin: 'edit', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'none', Management: 'none' },
  permissions:   { Admin: 'view', Operation: 'none', Operator: 'none', Rigger: 'none', Mechanic: 'none', Finance: 'none', Management: 'none' },
};

const can = (role, page) => (PERMISSIONS[page] && PERMISSIONS[page][role]) || 'none';
const canView = (role, page) => can(role, page) !== 'none';
const canEdit = (role, page) => can(role, page) === 'edit';

// Special-case action gates (layered on top of page perms)
const canCreateBooking = (role) => role === 'Admin';
const canDeleteBooking = (role) => role === 'Management';
const canEditMasterData = (role) => role === 'Admin';

const ROLE_LANDING = {
  Admin: 'dashboard',
  Operation: 'bookings',   // lands on Today's bookings
  Operator: 'mobile',
  Rigger: 'mobile',
  Mechanic: 'rm',
  Finance: 'export',
  Management: 'analytics',
};

// === Display categories for the User Management roster =================
// Roles drive permissions (above); these tidy categories drive how the
// User Management table is grouped & labelled. One category can fold in
// more than one underlying role.
const USER_CATEGORIES = ['Super Admin', 'Management', 'Account and Finance', 'Dispatch', 'Mechanic', 'Operator', 'Rigger'];
const ROLE_CATEGORY = {
  Admin: 'Super Admin',
  Operation: 'Account and Finance',
  Operator: 'Operator',
  Rigger: 'Rigger',
  Mechanic: 'Mechanic',
  Finance: 'Account and Finance',
  Management: 'Management',
};
const userCategory = (u) => u.category || ROLE_CATEGORY[u.role] || 'Operator';

const USERS = [
  // ---- Super Admin ----
  { id: 1, name: 'Teon Lee',  role: 'Admin',      email: 'admin@powleecrane.com',    phone: '+60 12-345 6789', status: 'Active', last: '2 min ago' },
  // ---- Account ----
  { id: 2, name: 'Lee Mei Yee',     role: 'Operation',  email: 'dispatch@powleecrane.com', phone: '+60 13-887 2210', status: 'Active', last: '5 min ago' },
  // ---- Dispatch ----
  { id: 3, name: 'Miss Wong',  role: 'Operation',  category: 'Dispatch', email: 'dispatch2@powleecrane.com', phone: '+60 12-553 8841', status: 'Active', last: '8 min ago' },
  { id: 4, name: 'Lim Kok Wai',   role: 'Operation',  category: 'Dispatch', email: 'dispatch3@powleecrane.com', phone: '+60 16-998 4420', status: 'Active', last: '32 min ago' },
  // ---- Operators ----
  { id: 10, name: 'Hisham',       role: 'Operator', email: 'hisham@powleecrane.com',   phone: '+60 16-789 7008', status: 'On Job',  last: 'On site' },
  { id: 11, name: 'Muthu',        role: 'Operator', email: 'muthu@powleecrane.com',    phone: '+60 16-374 3994', status: 'On Job',  last: 'On site' },
  { id: 12, name: 'Ganis',        role: 'Operator', email: 'ganis@powleecrane.com',    phone: '+60 16-721 5848', status: 'On Job',  last: 'On site' },
  { id: 13, name: 'Selva',        role: 'Operator', email: 'selva@powleecrane.com',    phone: '+60 16-986 7369', status: 'Active',  last: '1 hr ago' },
  { id: 14, name: 'Rohezal',      role: 'Operator', email: 'rohezal@powleecrane.com',  phone: '+60 13-660 5328', status: 'On Job',  last: 'On site' },
  { id: 15, name: 'Hairul',       role: 'Operator', email: 'hairul@powleecrane.com',   phone: '+60 19-430 5896', status: 'Active',  last: '3 hr ago' },
  { id: 16, name: 'Kanisan',      role: 'Operator', email: 'kanisan@powleecrane.com',  phone: '+60 16-797 3375', status: 'On Job',  last: 'On site' },
  { id: 17, name: 'Rajah',        role: 'Operator', email: 'rajah@powleecrane.com',    phone: '+60 16-770 3342', status: 'On Job',  last: 'On site' },
  { id: 18, name: 'Zorkapli',     role: 'Operator', email: 'zorkapli@powleecrane.com', phone: '+60 13-734 4312', status: 'Active',  last: '2 hr ago' },
  { id: 19, name: 'Zul30ton',     role: 'Operator', email: 'zul@powleecrane.com',      phone: '+60 12-748 7354', status: 'On Job',  last: 'On site' },
  { id: 20, name: 'Yusof',        role: 'Operator', email: 'yusof@powleecrane.com',    phone: '+60 18-375 4589', status: 'Active',  last: '4 hr ago' },
  { id: 21, name: 'Izzul',        role: 'Operator', email: 'izzul@powleecrane.com',    phone: '+60 10-251 7763', status: 'On Job',  last: 'On site' },
  { id: 22, name: 'Radzi',        role: 'Operator', email: 'radzi@powleecrane.com',    phone: '+60 18-288 0809', status: 'On Job',  last: 'On site' },
  { id: 23, name: 'Ahmad',        role: 'Operator', email: 'ahmad@powleecrane.com',    phone: '+60 11-2867 5289', status: 'Active', last: '1 hr ago' },
  { id: 24, name: 'Hanapi',       role: 'Operator', email: 'hanapi@powleecrane.com',   phone: '+60 11-2943 2457', status: 'On Job', last: 'On site' },
  { id: 25, name: 'Jembri',       role: 'Operator', email: 'jembri@powleecrane.com',   phone: '+60 11-1487 3758', status: 'Active', last: '2 hr ago' },
  { id: 26, name: 'Azizi',        role: 'Operator', email: 'azizi@powleecrane.com',    phone: '+60 18-781 1640', status: 'On Job',  last: 'On site' },
  { id: 27, name: 'Ah Chuan',     role: 'Operator', email: 'ahchuan@powleecrane.com',  phone: '+60 18-255 5868', status: 'Active',  last: '5 hr ago' },
  { id: 28, name: 'N/A',          role: 'Operator', email: '—',                        phone: '—',               status: 'Standby', last: 'Vacant slot' },
  { id: 29, name: 'Shafiq',       role: 'Operator', email: 'shafiq@powleecrane.com',   phone: '+60 11-2132 0705', status: 'On Job', last: 'On site' },
  { id: 30, name: 'Ah Hau (ganti)', role: 'Operator', email: 'ahhau@powleecrane.com',  phone: '—',               status: 'Standby', last: 'Relief / substitute' },
  { id: 31, name: 'Richard',      role: 'Operator', email: 'richard@powleecrane.com',  phone: '+60 12-847 0029', status: 'On Job',  last: 'On site' },
  { id: 32, name: 'Teon',         role: 'Operator', email: 'teon@powleecrane.com',     phone: '+60 16-713 6382', status: 'Active',  last: '3 hr ago' },
  // ---- Riggers ----
  { id: 33, name: 'A. Shafik',    role: 'Rigger', email: 'ashafik@powleecrane.com',  phone: '+60 13-278 7576', status: 'On Job',  last: 'On site' },
  { id: 34, name: 'Shyami',       role: 'Rigger', email: 'shyami@powleecrane.com',   phone: '+60 16-552 9087', status: 'On Job',  last: 'On site' },
  { id: 35, name: 'Irwan',        role: 'Rigger', email: 'irwan@powleecrane.com',    phone: '+60 13-901 4478', status: 'Active',  last: '1 hr ago' },
  // ---- Mechanics ----
  { id: 40, name: 'Awei',         role: 'Mechanic',   email: 'workshop@powleecrane.com', phone: '+60 16-223 4456', status: 'Active', last: '20 min ago' },
  { id: 41, name: 'Sathya',       role: 'Mechanic',   email: 'sathya@powleecrane.com',   phone: '+60 11-887 9911', status: 'Active', last: '1 day ago' },
  { id: 42, name: 'Melon',        role: 'Mechanic',   email: 'melon@powleecrane.com',    phone: '+60 18-664 2031', status: 'Active', last: '3 hr ago' },
  // ---- Finance & Management ----
  { id: 50, name: 'Miss Lim', role: 'Finance',    email: 'finance@powleecrane.com',  phone: '+60 19-554 8821', status: 'Active', last: 'Yesterday' },
  { id: 51, name: 'Pang Sek Chin',     role: 'Management', email: 'mgmt@powleecrane.com',     phone: '+60 17-223 4456', status: 'Active', last: '4 hr ago' },
];

// Today reference date — see klTodayISO()/TODAY defined above (Malaysia GMT+8).

// === Booking overlap detection ======================================
// Two time ranges overlap iff start1 < end2 AND start2 < end1.
// Returns the FIRST conflicting booking on the same plate + date, or null.
function findBookingOverlap({ plate, date, start, end, excludeId }) {
  if (!plate || !date || !start || !end) return null;
  return BOOKINGS.find(b =>
    b.id !== excludeId &&
    b.plate === plate &&
    b.date === date &&
    start < b.end &&
    b.start < end
  ) || null;
}

// Returns the FIRST conflicting booking where the same operator is already
// scheduled within the requested time window, or null.
function findOperatorOverlap({ operator, date, start, end, excludeId }) {
  if (!operator || operator === '—' || !date || !start || !end) return null;
  return BOOKINGS.find(b =>
    b.id !== excludeId &&
    b.operator === operator &&
    b.date === date &&
    start < b.end &&
    b.start < end
  ) || null;
}

// Returns the FIRST conflicting booking where the same rigger is already
// scheduled within the requested time window, or null. Riggers of '—' are skipped.
function findRiggerOverlap({ rigger, date, start, end, excludeId }) {
  if (!rigger || rigger === '—' || !date || !start || !end) return null;
  return BOOKINGS.find(b =>
    b.id !== excludeId &&
    b.rigger === rigger &&
    b.date === date &&
    start < b.end &&
    b.start < end
  ) || null;
}

Object.assign(window, {
  CATEGORIES, MACHINES, CUSTOMERS, LOCATIONS, OPERATORS, RIGGERS, SHIFT_OPTIONS, TOOLS,
  CERT_LEGEND, CERT_COLOR, CERT_LABEL,
  CERT_TODAY, CERT_RENEW_WINDOW_DAYS, certDaysLeft, certState, activeCerts, fmtCertDate, certReminders,
  machineLabel, bookingMachineLabel,
  BOOKINGS, WORK_ORDERS, STATUS_MAP, DAILY_NOTES,
  NOTIFICATIONS, REPAIR_TICKETS, MAINTENANCE, SERVICE_ITEMS, SERVICE_INTERVAL_MONTHS, MECHANICS, SUPPLIERS,
  SUPPLIER_DIRECTORY, STOCKS,
  ROLES, PERMISSIONS, can, canView, canEdit,
  canCreateBooking, canDeleteBooking, canEditMasterData,
  ROLE_LANDING, USERS, USER_CATEGORIES, ROLE_CATEGORY, userCategory, TODAY, addDaysISO, daysBetweenISO, klTodayISO, findBookingOverlap, findOperatorOverlap, findRiggerOverlap,
});
