/* Pelagia Portal — Payments, History, Vendors, Items, Sites, Cart, Users, Vessels, Accounts */
/* ═══════════════════ PAYMENTS ═══════════════════ */
const PaymentsPage = ({ go }) => {
const ready = ORDERS.filter(o => o.status === "MGR_APPROVED");
const sent = ORDERS.filter(o => o.status === "SENT_FOR_PAYMENT");
return (
<>
Payment queue
{ready.length} ready for payment · {sent.length} awaiting confirmation
Ready for payment
{ready.map(o => (
- Vessel
- {o.vessel}
- Vendor
- {o.vendor || —}
- Submitter
- {o.submitter}
- Approved
- {o.approved || "—"}
{inrFull(o.amount)}
))}
Processing — awaiting confirmation
{sent.map(o => (
- Vessel
- {o.vessel}
- Vendor
- {o.vendor}
- Submitter
- {o.submitter}
- Sent on
- May 09, 2026
{inrFull(o.amount)}
))}
{sent.length === 0 &&
Nothing currently processing.
}
>
);
};
/* ═══════════════════ HISTORY ═══════════════════ */
const HistoryPage = ({ go }) => (
<>
Order history
All POs across all statuses · apply filters then export
| PO Number | Title | Vessel | Submitter |
Status | Created | Amount |
{ORDERS.map(o => (
go("po-detail", o.id)}>
| {o.id} |
{o.title} |
{o.vessel} |
{o.submitter} |
|
{o.submitted || o.created || "—"} |
{inr(o.amount)} |
))}
>
);
/* ═══════════════════ VENDOR REGISTRY ═══════════════════ */
const VendorsPage = ({ go }) => {
const [showAdd, setShowAdd] = useS(false);
return (
<>
Vendor registry
{VENDORS.length} vendors · {VENDORS.filter(v => v.verified).length} verified via GSTIN lookup
{showAdd && setShowAdd(false)} />}
| Vendor ID | Name | Contact |
Items | Verified | Status | |
{VENDORS.map(v => (
go("vendor-detail", v.id)}>
| {v.vid || Pending} |
{v.name}
{v.city} · GSTIN {v.gstin}
|
{v.contact}
{v.email}
|
{[42, 18, 64, 7, 22, 31][VENDORS.indexOf(v)]} |
{v.verified
? Verified
: —}
|
{v.active ? "Active" : "Inactive"} |
|
))}
>
);
};
const AddVendorPanel = ({ onClose }) => {
const [step, setStep] = useS(1); // 1 type GSTIN, 2 captcha, 3 verified
return (
Close} className="action-panel" style={{ marginBottom: 18 }}>
Look up the vendor's GSTIN to auto-fill name, address, and pincode. Manual entry is allowed if needed.
{step === 1 && (
)}
{step >= 2 && (
)}
{step >= 2 && (
)}
{step === 3 && (
<>
Verified. Legal name, address, and pincode have been pulled from the GST portal.
>
)}
);
};
/* ═══════════════════ VENDOR DETAIL ═══════════════════ */
const VendorDetailPage = ({ go, id }) => {
const v = VENDORS.find(x => x.id === id) || VENDORS[0];
return (
<>
{v.name}
{v.vid ? <>{v.vid}·> : null}
{v.verified && <> GSTIN verified·>}
{v.active ? "Active" : "Inactive"}
Items supplied
| Code | Product | Last quoted | Last updated | |
{PRODUCTS.slice(0, 5).map(p => (
go("item-detail", p.id)}>
| {p.code} |
{p.name} |
{inrFull(p.lastPrice)} |
{p.updated} |
|
))}
Recent purchase orders
| PO Number | Status | Vessel | Created | Amount |
{ORDERS.slice(0, 6).map(o => (
go("po-detail", o.id)}>
| {o.id} |
|
{o.vessel} |
{o.submitted || "—"} |
{inr(o.amount)} |
))}
- GSTIN
- {v.gstin}
- Pincode
- {v.pin}
- City
- {v.city}
- Contact
- {v.contact}
- Mobile
- {v.phone}
- Email
- {v.email}
48/2A Bristow Road, Willingdon Island,
Kochi, Kerala — {v.pin}
>
);
};
/* ═══════════════════ ITEMS CATALOGUE ═══════════════════ */
const ItemsPage = ({ go }) => (
<>
Item catalogue
{PRODUCTS.length} products · auto-synced when POs are marked as paid
Items are added automatically when a PO is marked as paid. Manual entry is reserved for ADMIN.
| Code | Name | Description |
Vendors | Last price | Last vendor | Updated | |
{PRODUCTS.map(p => (
go("item-detail", p.id)}>
| {p.code} |
{p.name} |
{p.desc} |
{p.vendors} |
{inr(p.lastPrice)} |
{p.lastVendor} |
{p.updated} |
{p.active ? "Active" : "Inactive"} |
))}
>
);
/* ═══════════════════ ITEM DETAIL ═══════════════════ */
const ItemDetailPage = ({ go, id }) => {
const p = PRODUCTS.find(x => x.id === id) || PRODUCTS[0];
const [siteFilter, setSiteFilter] = useS("");
const vendors = [...ITEM_VENDORS].sort((a, b) => siteFilter ? a.distance - b.distance : 0);
const max = Math.max(...vendors.map(v => v.price));
const min = Math.min(...vendors.map(v => v.price));
return (
<>
{p.name}
{p.code}·
Active·
{p.desc}
Anchor Supply Traders} />
Konark Industrial Spares} />
of 4 sites} />
Unit price · INR}>
{vendors.map((v, i) => (
{inr(v.price)}
))}
Cochin Port Depot · 18 ea
Chennai South Dock · 6 ea
Visakhapatnam Yard · 14 ea
Mumbai BPX Office · 0 ea
Inventory is updated when consumption is logged at the site. Click a chip to open site detail.
Vendor pricing
Sort by distance from
| Vendor | Verified |
Unit price |
{siteFilter && Distance | }
Last updated |
|
{vendors.map((v, i) => (
|
{v.closest && siteFilter && ★}
{v.vendor}
|
{v.verified ? Verified : —} |
{inrFull(v.price)} |
{siteFilter && {v.distance} km | }
{v.updated} |
|
))}
>
);
};
Object.assign(window, { PaymentsPage, HistoryPage, VendorsPage, VendorDetailPage, ItemsPage, ItemDetailPage });