first commit
This commit is contained in:
842
test/fixtures/demo_stops.dart
vendored
Normal file
842
test/fixtures/demo_stops.dart
vendored
Normal file
@@ -0,0 +1,842 @@
|
||||
|
||||
// Shared mock booking data for development/testing
|
||||
|
||||
List<Map<String, dynamic>> getMockQueues() {
|
||||
final now = DateTime.now();
|
||||
return [
|
||||
{
|
||||
'orderid': 'MOCK-Q-1001',
|
||||
'pickupid': 'del-mock-q-1001',
|
||||
'orderheaderid': '10001',
|
||||
'orderstatus': 'accepted',
|
||||
'pickupcustomer': 'Priya Sharma',
|
||||
'pickupaddress': '45, Lake View Apartments, Race Course',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9558',
|
||||
'pickuplat': '11.0243',
|
||||
'pickuplong': '76.9652',
|
||||
'kms': '2.1',
|
||||
'Quantity': '3',
|
||||
'notes': 'Documents parcel - handover at door',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 15))
|
||||
.toIso8601String(),
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-Q-1002',
|
||||
'pickupid': 'del-mock-q-1002',
|
||||
'orderheaderid': '10002',
|
||||
'orderstatus': '',
|
||||
'pickupcustomer': 'Arun Venkatesh',
|
||||
'pickupaddress': '23, Teachers Colony, Saibaba Colony',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9678',
|
||||
'pickuplat': '11.0312',
|
||||
'pickuplong': '76.9721',
|
||||
'kms': '1.5',
|
||||
'Quantity': '8',
|
||||
'notes': 'Clothes & accessories - packed in bags',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 30))
|
||||
.toIso8601String(),
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-Q-1003',
|
||||
'pickupid': 'del-mock-q-1003',
|
||||
'orderheaderid': '10003',
|
||||
'orderstatus': '',
|
||||
'pickupcustomer': 'Meena Krishnan',
|
||||
'pickupaddress': '5/2, North Avenue, Vadavalli',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9902',
|
||||
'pickuplat': '11.0358',
|
||||
'pickuplong': '76.9985',
|
||||
'kms': '3.2',
|
||||
'Quantity': '12',
|
||||
'notes': 'Electronics item - handle with care',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 45))
|
||||
.toIso8601String(),
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-Q-1004',
|
||||
'pickupid': 'del-mock-q-1004',
|
||||
'orderheaderid': '10004',
|
||||
'orderstatus': 'accepted',
|
||||
'pickupcustomer': 'Vikram Singh',
|
||||
'pickupaddress': '88, Royal Nagar, Singanallur',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9428',
|
||||
'pickuplat': '11.0198',
|
||||
'pickuplong': '76.9512',
|
||||
'kms': '1.8',
|
||||
'Quantity': '5',
|
||||
'notes': 'Gift items - fragile, handle gently',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 20))
|
||||
.toIso8601String(),
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-Q-1005',
|
||||
'pickupid': 'del-mock-q-1005',
|
||||
'orderheaderid': '10005',
|
||||
'orderstatus': '',
|
||||
'pickupcustomer': 'Divya Menon',
|
||||
'pickupaddress': '120, West Street, Thudiyalur',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9889',
|
||||
'pickuplat': '11.0318',
|
||||
'pickuplong': '76.9965',
|
||||
'kms': '2.8',
|
||||
'Quantity': '15',
|
||||
'notes': 'Books and stationery - secure packaging',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 60))
|
||||
.toIso8601String(),
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> getMockBookingPageItems() {
|
||||
final now = DateTime.now();
|
||||
return [
|
||||
{
|
||||
'orderid': 'MOCK-B-3001',
|
||||
'pickupid': '3001',
|
||||
'orderheaderid': '103001',
|
||||
'orderstatus': 'accepted',
|
||||
'step': 1,
|
||||
'pickupcustomer': 'Lakshmi Narayanan',
|
||||
'pickupaddress': '67, East Gate, Uppilipalayam',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9500',
|
||||
'pickuplat': '11.0168',
|
||||
'pickuplong': '76.9558',
|
||||
'droplat': '11.0168',
|
||||
'droplon': '76.9558',
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
'kms': '2.4',
|
||||
'Quantity': '6',
|
||||
'notes': 'Ready for pickup - ring the bell',
|
||||
'pickupcontactno': '9876543210',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 12))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-B-3002',
|
||||
'pickupid': '3002',
|
||||
'orderheaderid': '103002',
|
||||
'orderstatus': 'pending',
|
||||
'step': 2,
|
||||
'pickupcustomer': 'Rajesh Bhat',
|
||||
'pickupaddress': '4, Sunshine Apartments, R.S. Puram',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9419',
|
||||
'pickuplat': '11.0347',
|
||||
'pickuplong': '76.9468',
|
||||
'droplat': '11.0347',
|
||||
'droplon': '76.9468',
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
'kms': '3.1',
|
||||
'Quantity': '4',
|
||||
'notes': 'Parcel - handle with care',
|
||||
'pickupcontactno': '9876543211',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 24))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-B-3003',
|
||||
'pickupid': '3003',
|
||||
'orderheaderid': '103003',
|
||||
'orderstatus': 'pending',
|
||||
'step': 3,
|
||||
'pickupcustomer': 'Neha Agarwal',
|
||||
'pickupaddress': '22, Lake View Road, Koundampalayam',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '77.0397',
|
||||
'pickuplat': '11.0254',
|
||||
'pickuplong': '77.0102',
|
||||
'droplat': '11.0254',
|
||||
'droplon': '77.0102',
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
'kms': '4.6',
|
||||
'Quantity': '2',
|
||||
'notes': 'Urgent pickup - handle with care',
|
||||
'pickupcontactno': '9876543212',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 38))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-B-3004',
|
||||
'pickupid': '3004',
|
||||
'orderheaderid': '103004',
|
||||
'orderstatus': 'skipped',
|
||||
'step': 4,
|
||||
'pickupcustomer': 'Anjali Nair',
|
||||
'pickupaddress': '10, New Colony, Saravanampatti',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplon': '76.9600',
|
||||
'pickuplat': '11.0198',
|
||||
'pickuplong': '76.9512',
|
||||
'droplat': '11.0198',
|
||||
'droplon': '76.9512',
|
||||
'riderslat': '11.0180',
|
||||
'riderslon': '76.9580',
|
||||
'kms': '1.8',
|
||||
'Quantity': '5',
|
||||
'notes': 'Previously skipped - resume when ready',
|
||||
'pickupcontactno': '9876543213',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 45))
|
||||
.toIso8601String(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> getMockPickups() {
|
||||
final now = DateTime.now();
|
||||
return [
|
||||
{
|
||||
'orderid': 'MOCK-D-2001',
|
||||
'pickupid': 'del-mock-d-2001',
|
||||
'orderstatus': 'picked',
|
||||
'step': 1,
|
||||
'pickupcustomer': 'Sarah Johnson',
|
||||
'pickupaddress': '42 Maple Street, Apt 3B, New York, NY 10001',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplong': -74.0060,
|
||||
'pickuplat': 40.7580,
|
||||
'pickuplon': -73.9855,
|
||||
'kms': '3.2',
|
||||
'notes': 'Ring doorbell, leave at door',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 25))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-D-2002',
|
||||
'pickupid': 'del-mock-d-2002',
|
||||
'orderstatus': 'picked',
|
||||
'step': 2,
|
||||
'pickupcustomer': 'Michael Chen',
|
||||
'pickupaddress': '158 Broadway, Floor 5, New York, NY 10013',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplong': -74.0020,
|
||||
'pickuplat': 40.7580,
|
||||
'pickuplon': -73.9855,
|
||||
'kms': '1.8',
|
||||
'notes': 'Call upon arrival, building requires access code #4521',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 40))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-D-2003',
|
||||
'pickupid': 'del-mock-d-2003',
|
||||
'orderstatus': 'picked',
|
||||
'step': 3,
|
||||
'pickupcustomer': 'Emily Rodriguez',
|
||||
'pickupaddress': '275 7th Avenue, Suite 1200, New York, NY 10011',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplong': -73.9950,
|
||||
'pickuplat': 40.7580,
|
||||
'pickuplon': -73.9855,
|
||||
'kms': '2.5',
|
||||
'notes': 'Pickup to reception desk',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 55))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-D-2004',
|
||||
'pickupid': 'del-mock-d-2004',
|
||||
'orderstatus': 'picked',
|
||||
'step': 4,
|
||||
'pickupcustomer': 'James Wilson',
|
||||
'pickupaddress': '88 University Place, Ground Floor, New York, NY 10003',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplong': -73.9920,
|
||||
'pickuplat': 40.7580,
|
||||
'pickuplon': -73.9855,
|
||||
'kms': '1.2',
|
||||
'notes': '',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 70))
|
||||
.toIso8601String(),
|
||||
},
|
||||
{
|
||||
'orderid': 'MOCK-D-2005',
|
||||
'pickupid': 'del-mock-d-2005',
|
||||
'orderstatus': 'skipped',
|
||||
'step': 5,
|
||||
'pickupcustomer': 'Anna Kim',
|
||||
'pickupaddress': '301 W 53rd Street, Apt 12A, New York, NY 10019',
|
||||
'tenantname': 'Miler Logistics',
|
||||
'pickuplong': -73.9850,
|
||||
'pickuplat': 40.7580,
|
||||
'pickuplon': -73.9855,
|
||||
'kms': '4.1',
|
||||
'notes': 'Cash payment expected',
|
||||
'expected_pickup_time': now
|
||||
.add(const Duration(minutes: 90))
|
||||
.toIso8601String(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// DEMO TRIPS — three slot windows, every stop type, every decision state.
|
||||
//
|
||||
// ── This is a TEST FIXTURE. It does not ship. ──
|
||||
//
|
||||
// It used to live in `lib/data/mock_bookings.dart` and fill Home, Bookings and
|
||||
// the handoff screen whenever the live backend answered with an empty list —
|
||||
// gated on `kDebugMode`, which sounds safe and is not: the person running the
|
||||
// debug build is the person deciding whether the feature works, and a screen
|
||||
// full of convincing invented stops is exactly how a dead endpoint gets signed
|
||||
// off. The app now shows what the hub actually said, including nothing.
|
||||
//
|
||||
// What survives is its second, legitimate job: a rich, deterministic route to
|
||||
// test the pure `Trip` grouping logic against. Three trips covering every stop
|
||||
// type in every state is a better fixture than anything a test would build by
|
||||
// hand, so it moved here rather than being deleted.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Three trips covering every stop type in every state the rider can see.
|
||||
///
|
||||
/// Trip 1 (09:00–12:00) — part-worked. A completed pickup AND a completed
|
||||
/// delivery, a combined stop in progress, a skipped
|
||||
/// delivery, and two still awaiting a decision. This
|
||||
/// is the tab to look at for the locked rows, the
|
||||
/// amber skip state and the completion ring.
|
||||
/// Trip 2 (12:00–15:00) — delivery-heavy, all undecided. Multi-parcel drops,
|
||||
/// a prepaid run, and two combined stops.
|
||||
/// Trip 3 (15:00–18:00) — combined-heavy, all undecided, and the longest,
|
||||
/// so select-all and multi-select are worth using.
|
||||
///
|
||||
/// **Different data per miler.** This used to return one hard-coded list, so
|
||||
/// every account — Ramesh, the next tester, the demo rider — opened Home to the
|
||||
/// exact same six customers, and the same `DM-21xx` order ids. Identical ids
|
||||
/// across accounts is the worse half: accept/reject is persisted locally by
|
||||
/// order id, so decisions made while signed in as one miler came back as
|
||||
/// already-accepted stops for the next one.
|
||||
///
|
||||
/// So the *skeleton* is fixed and the *identity* is per rider. Which trip a stop
|
||||
/// is in, its step, type, status and time window never change — that is what
|
||||
/// guarantees every UI branch still has something to render, for every miler.
|
||||
/// The customer, address, coordinates, parcel counts, cash and order ids are
|
||||
/// drawn from [riderId] / [riderName], deterministically: the same miler gets
|
||||
/// the same route every launch, two milers never get the same one.
|
||||
///
|
||||
/// Called with no rider (signed out) it still yields a valid route — seed 0.
|
||||
List<Map<String, dynamic>> getDemoTripStops({String? riderName, int? riderId}) {
|
||||
final now = DateTime.now();
|
||||
DateTime at(int hour, int minute) =>
|
||||
DateTime(now.year, now.month, now.day, hour, minute);
|
||||
|
||||
final seed = _demoSeed(riderName, riderId);
|
||||
final rng = _DemoRandom(seed);
|
||||
|
||||
// Three digits stamped into every order id, so one miler's demo stops can
|
||||
// never be mistaken — by the accepted/rejected store or by a human reading
|
||||
// logs — for another's.
|
||||
final tag = 100 + (seed % 900);
|
||||
|
||||
// Where this miler's route runs. Stepping through the shared pool by a stride
|
||||
// coprime with its length visits 18 distinct places, and a rider-specific
|
||||
// start + stride means two milers overlap in few of them.
|
||||
final start = seed % _demoPlaces.length;
|
||||
final stride = const [1, 5, 7, 11, 13][seed % 5];
|
||||
|
||||
final stops = <Map<String, dynamic>>[];
|
||||
for (var i = 0; i < _demoSkeleton.length; i++) {
|
||||
final slot = _demoSkeleton[i];
|
||||
final place = _demoPlaces[(start + i * stride) % _demoPlaces.length];
|
||||
|
||||
// Loads vary per miler, but stay in the range each stop type implies: a
|
||||
// delivery drops what it carries, a pickup collects, a combined does both.
|
||||
final int? deliveryQty = slot.type == 'pickup'
|
||||
? null
|
||||
: rng.between(1, slot.type == 'delivery' ? 4 : 3);
|
||||
final int? pickupQty = slot.type == 'delivery'
|
||||
? null
|
||||
: rng.between(1, slot.type == 'pickup' ? 8 : 5);
|
||||
|
||||
stops.add(
|
||||
_demoStop(
|
||||
id: 'DM-$tag${slot.code}',
|
||||
step: slot.step,
|
||||
type: slot.type,
|
||||
status: slot.status,
|
||||
customer: place.customer,
|
||||
address: place.address,
|
||||
lat: place.lat,
|
||||
lng: place.lng,
|
||||
qty: pickupQty ?? deliveryQty ?? 1,
|
||||
deliveryQty: deliveryQty,
|
||||
pickupQty: pickupQty,
|
||||
// Round sums to the nearest ten — a COD figure of ₹1247 reads as a bug.
|
||||
cash: slot.cod ? (rng.between(15, 140) * 10).toDouble() : null,
|
||||
notes: slot.notes,
|
||||
due: at(slot.hour, slot.minute),
|
||||
),
|
||||
);
|
||||
}
|
||||
return stops;
|
||||
}
|
||||
|
||||
/// The Bookings tab's demo route — the same stops Home hands out, in the states
|
||||
/// a rider who has *already accepted them* would see.
|
||||
///
|
||||
/// Bookings was empty on the live backend for two separate reasons, and fixing
|
||||
/// only one would have left it empty anyway:
|
||||
///
|
||||
/// 1. Its mock fallback was gated on `!ApiConfig.useNewApi`, and the new API
|
||||
/// is the default — the same gate Home and Earnings had.
|
||||
/// 2. Even with stops injected, the tab drops anything still pending: it
|
||||
/// shows work the rider has *taken on*, and `getDemoTripStops` returns
|
||||
/// mostly `status: 'new'`, which that filter removes. So demo stops have
|
||||
/// to arrive already accepted, or they vanish silently.
|
||||
///
|
||||
/// This takes the miler's own route and rewrites the first twelve stops into a
|
||||
/// believable working day, so the tab has something in every state it can
|
||||
/// render: a couple finished (green rail), one active (the card that blocks the
|
||||
/// others), one skipped (amber, awaiting a return), and the rest queued.
|
||||
List<Map<String, dynamic>> getDemoBookings({String? riderName, int? riderId}) {
|
||||
final stops = getDemoTripStops(riderName: riderName, riderId: riderId);
|
||||
if (stops.isEmpty) return stops;
|
||||
|
||||
// Trips 1 and 2 — twelve stops is a full screen's worth of scrolling without
|
||||
// pretending a rider has a forty-stop day.
|
||||
final slice = stops.take(12).toList();
|
||||
|
||||
// Positions chosen so the progress bar shows every colour it has, and the
|
||||
// active stop is early enough that queued stops sit visibly below it.
|
||||
const statuses = <int, String>{
|
||||
0: 'picked', // done
|
||||
1: 'delivered', // done
|
||||
2: 'active', // the one he is on
|
||||
3: 'skipped', // come back to it
|
||||
};
|
||||
|
||||
return [
|
||||
for (var i = 0; i < slice.length; i++)
|
||||
<String, dynamic>{
|
||||
...slice[i],
|
||||
// Everything else is accepted: taken on, not yet started. That is the
|
||||
// state the Bookings filter is looking for.
|
||||
'orderstatus': statuses[i] ?? 'accepted',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/// Stable per-miler seed. FNV-1a over the identity, so neighbouring rider ids
|
||||
/// (9998, 9999) land far apart instead of drawing near-identical routes.
|
||||
int _demoSeed(String? riderName, int? riderId) {
|
||||
final key = (riderId != null && riderId > 0)
|
||||
? 'id:$riderId'
|
||||
: 'name:${(riderName ?? '').trim().toLowerCase()}';
|
||||
if (key == 'name:') return 0;
|
||||
var h = 2166136261;
|
||||
for (final c in key.codeUnits) {
|
||||
h ^= c;
|
||||
h = (h * 16777619) & 0xFFFFFFFF;
|
||||
}
|
||||
return h & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
/// Deterministic per-miler number source. Not `dart:math`'s Random — this must
|
||||
/// give the same route on every launch for the same rider, and be seedable from
|
||||
/// an id rather than the clock.
|
||||
class _DemoRandom {
|
||||
int _state;
|
||||
_DemoRandom(int seed) : _state = (seed | 1) & 0x7FFFFFFF;
|
||||
|
||||
int between(int min, int max) {
|
||||
_state = (_state * 1103515245 + 12345) & 0x7FFFFFFF;
|
||||
return min + ((_state >> 8) % (max - min + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// A place a demo stop can happen at. The pool is shared; which slice of it a
|
||||
/// miler gets is decided by their seed.
|
||||
class _DemoPlace {
|
||||
final String customer;
|
||||
final String address;
|
||||
final double lat;
|
||||
final double lng;
|
||||
const _DemoPlace(this.customer, this.address, this.lat, this.lng);
|
||||
}
|
||||
|
||||
/// 36 addresses across Coimbatore — twice what one miler's day uses, so two
|
||||
/// milers' routes look properly different rather than reshuffled.
|
||||
const List<_DemoPlace> _demoPlaces = [
|
||||
_DemoPlace(
|
||||
'Priya Sharma',
|
||||
'45, Lake View Apartments, Race Course, Coimbatore',
|
||||
11.0243,
|
||||
76.9558,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Arun Venkatesh',
|
||||
'23, Teachers Colony, Saibaba Colony, Coimbatore',
|
||||
11.0312,
|
||||
76.9678,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Meena Krishnan',
|
||||
'5/2, North Avenue, Vadavalli, Coimbatore',
|
||||
11.0358,
|
||||
76.9902,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Ravi Subramanian',
|
||||
'12A, Puliakulam Road, Coimbatore',
|
||||
11.0021,
|
||||
76.9721,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Sri Balaji Stores',
|
||||
'19, Thadagam Road, Venkitapuram, Coimbatore',
|
||||
11.0289,
|
||||
76.9312,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Sundar Textiles',
|
||||
'78, Cross Cut Road, Gandhipuram, Coimbatore',
|
||||
11.0168,
|
||||
76.9558,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Kavitha Ramesh',
|
||||
'12, Bharathi Park Road, Coimbatore',
|
||||
11.0089,
|
||||
76.9712,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Hari Prasad',
|
||||
'7, DB Road, RS Puram, Coimbatore',
|
||||
11.0043,
|
||||
76.9498,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Lakshmi Stores',
|
||||
'61, Trichy Road, Ramanathapuram, Coimbatore',
|
||||
10.9931,
|
||||
76.9887,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Anand Electronics',
|
||||
'3, Oppanakara Street, Town Hall, Coimbatore',
|
||||
10.9975,
|
||||
76.9601,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Nandhini Bakery',
|
||||
'54, 100 Feet Road, Gandhipuram, Coimbatore',
|
||||
11.0198,
|
||||
76.9673,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Divya Fashions',
|
||||
'9, Nava India Road, Peelamedu, Coimbatore',
|
||||
11.0271,
|
||||
77.0021,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Ganesh Traders',
|
||||
'134, Avinashi Road, Hope College, Coimbatore',
|
||||
11.0301,
|
||||
77.0142,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Rekha Nair',
|
||||
'27, Kalapatti Main Road, Coimbatore',
|
||||
11.0521,
|
||||
77.0312,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Bright Pharmacy',
|
||||
'15, Mettupalayam Road, Thudiyalur, Coimbatore',
|
||||
11.0712,
|
||||
76.9401,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Selvam Hardware',
|
||||
'88, Sathy Road, Ganapathy, Coimbatore',
|
||||
11.0432,
|
||||
76.9821,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Vetri Apartments',
|
||||
'4B, Saravanampatti, Coimbatore',
|
||||
11.0798,
|
||||
77.0089,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Karthik Rajan',
|
||||
'31, Vilankurichi Road, Coimbatore',
|
||||
11.0644,
|
||||
77.0201,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Muthu Silks',
|
||||
'22, Raja Street, Town Hall, Coimbatore',
|
||||
10.9968,
|
||||
76.9585,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Aishwarya Gopal',
|
||||
'8, Kamaraj Road, Sowripalayam, Coimbatore',
|
||||
10.9924,
|
||||
76.9974,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Velan Provisions',
|
||||
'41, Ukkadam Main Road, Coimbatore',
|
||||
10.9861,
|
||||
76.9563,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Deepa Iyer',
|
||||
'16, TV Samy Road, RS Puram, Coimbatore',
|
||||
11.0071,
|
||||
76.9531,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Kongu Steel Mart',
|
||||
'102, Mettupalayam Road, Kavundampalayam, Coimbatore',
|
||||
11.0489,
|
||||
76.9382,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Sathya Agencies',
|
||||
'7, Perur Main Road, Kuniamuthur, Coimbatore',
|
||||
10.9639,
|
||||
76.9302,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Ramya Sundaram',
|
||||
'63, Perur Main Road, Kuniamuthur, Marudhamalai Road, Vadavalli, Coimbatore - 634783 ',
|
||||
11.0301,
|
||||
76.9151,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Green Leaf Grocers',
|
||||
'29, Kovaipudur Main Road, Coimbatore',
|
||||
10.9291,
|
||||
76.9128,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Prakash Auto Parts',
|
||||
'55, Sungam Bypass Road, Coimbatore',
|
||||
10.9832,
|
||||
76.9752,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Janaki Ammal',
|
||||
'3, Vivekananda Road, Ram Nagar, Coimbatore',
|
||||
11.0092,
|
||||
76.9663,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Coimbatore Book House',
|
||||
'19, Bashyakarlu Road, RS Puram, Coimbatore',
|
||||
11.0038,
|
||||
76.9457,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Tharun Sports',
|
||||
'74, Tatabad, Gandhipuram, Coimbatore',
|
||||
11.0212,
|
||||
76.9631,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Malathi Nursing Home',
|
||||
'12, Trichy Road, Singanallur, Coimbatore',
|
||||
10.9948,
|
||||
77.0298,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Sowmya Devi',
|
||||
'47, Kurichi Main Road, Coimbatore',
|
||||
10.9418,
|
||||
76.9601,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Ashok Timbers',
|
||||
'91, Palakkad Main Road, Madukkarai, Coimbatore',
|
||||
10.9061,
|
||||
76.9327,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Nithya Sweets',
|
||||
'5, Cheran Managar, Kalapatti, Coimbatore',
|
||||
11.0562,
|
||||
77.0221,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Vasanth Motors',
|
||||
'66, Karumathampatti Road, Neelambur, Coimbatore',
|
||||
11.0402,
|
||||
77.1012,
|
||||
),
|
||||
_DemoPlace(
|
||||
'Elango Krishnamoorthy',
|
||||
'18, Chinnavedampatti Road, Coimbatore',
|
||||
11.0601,
|
||||
76.9902,
|
||||
),
|
||||
];
|
||||
|
||||
/// One position on the day. Everything here is the same for every miler — this
|
||||
/// is the state-coverage contract the demo data exists to provide.
|
||||
class _DemoSlot {
|
||||
/// Trailing digits of the order id: trip number + step. Kept stable so a
|
||||
/// given miler's stop 3 of trip 2 is always `…2203`.
|
||||
final String code;
|
||||
final int step;
|
||||
|
||||
/// pickup | delivery | combined
|
||||
final String type;
|
||||
|
||||
/// new | picked | delivered | arrived | skipped
|
||||
final String status;
|
||||
final int hour;
|
||||
final int minute;
|
||||
|
||||
/// Whether this stop carries cash. The amount varies per miler; whether the
|
||||
/// COD branch renders at all does not.
|
||||
final bool cod;
|
||||
final String? notes;
|
||||
|
||||
const _DemoSlot(
|
||||
this.code,
|
||||
this.step,
|
||||
this.type,
|
||||
this.hour,
|
||||
this.minute, {
|
||||
this.status = 'new',
|
||||
this.cod = false,
|
||||
this.notes,
|
||||
});
|
||||
}
|
||||
|
||||
const List<_DemoSlot> _demoSkeleton = [
|
||||
// ── Trip 1 · 09:00 – 12:00 · part-worked ────────────────────────────────
|
||||
_DemoSlot('2101', 1, 'pickup', 9, 20, status: 'picked'), // done
|
||||
// A finished DELIVERY, not just a finished pickup.
|
||||
_DemoSlot('2102', 2, 'delivery', 9, 55, status: 'delivered'),
|
||||
// Active → the locked "In progress" row.
|
||||
_DemoSlot('2103', 3, 'combined', 10, 30, status: 'arrived', cod: true),
|
||||
_DemoSlot(
|
||||
'2104',
|
||||
4,
|
||||
'delivery',
|
||||
10,
|
||||
50,
|
||||
status: 'skipped',
|
||||
notes: 'Customer asked to come back after 11am',
|
||||
),
|
||||
_DemoSlot('2105', 5, 'combined', 11, 15),
|
||||
_DemoSlot(
|
||||
'2106',
|
||||
6,
|
||||
'pickup',
|
||||
11,
|
||||
40,
|
||||
notes: 'Bulk order — ask for the back entrance',
|
||||
),
|
||||
|
||||
// ── Trip 2 · 12:00 – 15:00 · delivery-heavy, all undecided ──────────────
|
||||
_DemoSlot('2201', 1, 'delivery', 12, 15),
|
||||
_DemoSlot('2202', 2, 'delivery', 12, 40, notes: 'Buzz flat 3B'),
|
||||
_DemoSlot('2203', 3, 'combined', 13, 5),
|
||||
_DemoSlot('2204', 4, 'pickup', 13, 35, cod: true),
|
||||
// Cash on the pickup leg of a combined stop.
|
||||
_DemoSlot('2205', 5, 'combined', 14, 0, cod: true),
|
||||
_DemoSlot('2206', 6, 'delivery', 14, 35),
|
||||
|
||||
// ── Trip 3 · 15:00 – 18:00 · combined-heavy, all undecided ──────────────
|
||||
_DemoSlot('2301', 1, 'combined', 15, 20),
|
||||
_DemoSlot('2302', 2, 'delivery', 15, 50),
|
||||
_DemoSlot(
|
||||
'2303',
|
||||
3,
|
||||
'combined',
|
||||
16,
|
||||
15,
|
||||
cod: true,
|
||||
notes: 'Cold chain box — do not leave in the sun',
|
||||
),
|
||||
_DemoSlot(
|
||||
'2304',
|
||||
4,
|
||||
'pickup',
|
||||
16,
|
||||
45,
|
||||
cod: true,
|
||||
notes: 'Heavy items — bring the large box',
|
||||
),
|
||||
_DemoSlot('2305', 5, 'combined', 17, 15),
|
||||
_DemoSlot('2306', 6, 'delivery', 17, 45),
|
||||
];
|
||||
|
||||
/// Builds one demo stop in the legacy stop shape the UI reads.
|
||||
Map<String, dynamic> _demoStop({
|
||||
required String id,
|
||||
required int step,
|
||||
required String type,
|
||||
required String customer,
|
||||
required String address,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required DateTime due,
|
||||
String status = 'new',
|
||||
int qty = 1,
|
||||
int? deliveryQty,
|
||||
int? pickupQty,
|
||||
double? cash,
|
||||
String? notes,
|
||||
}) {
|
||||
return <String, dynamic>{
|
||||
'orderid': id,
|
||||
'pickupid': id.replaceAll('DM-', ''),
|
||||
'orderheaderid': id.replaceAll('DM-', ''),
|
||||
'pickuplocationid': '1',
|
||||
'orderstatus': status,
|
||||
'step': step,
|
||||
'type': type,
|
||||
'pickupcustomer': customer,
|
||||
'tenantname': 'Doormile',
|
||||
'pickupaddress': address,
|
||||
'pickupcontactno': '9876543210',
|
||||
'pickuplat': '$lat',
|
||||
'pickuplon': '$lng',
|
||||
'pickuplong': '$lng',
|
||||
'Quantity': '$qty',
|
||||
if (deliveryQty != null) 'deliveryqty': '$deliveryQty',
|
||||
if (pickupQty != null) 'pickupqty': '$pickupQty',
|
||||
if (cash != null) 'collectionamt': '$cash',
|
||||
if (notes != null) 'notes': notes,
|
||||
'weight': '${(qty * 1.4).toStringAsFixed(1)}',
|
||||
'expected_pickup_time': due.toIso8601String(),
|
||||
'otp': type == 'pickup' ? '' : '4821',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user