mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 17:45:42 +00:00
feat: add shipping line companies management
- Implement ShippingLineCompaniesService for registering and managing shipping line companies. - Create ResendActivationAction component for resending activation links to shipping lines. - Develop ShippingLineCompaniesPage for listing and registering shipping lines with validation. - Introduce shippingLineCompanies.service for API interactions related to shipping lines. - Define types for shipping line companies, including registration and pagination. - Add placeholder pages for shipping line portal, including home, bookings, help, invoices, and settings.
This commit is contained in:
@@ -107,23 +107,20 @@ function getActivePage(
|
||||
activePath: string,
|
||||
): { label: string } | null {
|
||||
const path = activePath.toLowerCase();
|
||||
for (const item of items) {
|
||||
if (
|
||||
path === item.href.toLowerCase() ||
|
||||
path.startsWith(item.href.toLowerCase() + "/")
|
||||
) {
|
||||
return { label: item.label };
|
||||
}
|
||||
if (item.children) {
|
||||
const childMatch = item.children.find(
|
||||
(c) =>
|
||||
path === c.href.toLowerCase() ||
|
||||
path.startsWith(c.href.toLowerCase() + "/"),
|
||||
);
|
||||
if (childMatch) return { label: childMatch.label };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
// Longest match wins, for the same reason as the sidebar's isItemActive:
|
||||
// a nested href like "/shipping-line/bookings" must beat its "/shipping-line"
|
||||
// parent, which a first-match-wins scan would report as "Home".
|
||||
const best = items
|
||||
.flatMap((item) => [item, ...(item.children ?? [])])
|
||||
.filter(
|
||||
(item) =>
|
||||
path === item.href.toLowerCase() ||
|
||||
path.startsWith(item.href.toLowerCase() + "/"),
|
||||
)
|
||||
.sort((a, b) => b.href.length - a.href.length)[0];
|
||||
|
||||
return best ? { label: best.label } : null;
|
||||
}
|
||||
|
||||
const navClassNames = (active: boolean) => {
|
||||
@@ -262,9 +259,19 @@ export function AppLayout({
|
||||
const serviceLabel = (m: ServiceType) => PROFILE_TYPE_LABELS[m] ?? m;
|
||||
const isSuspendedAppeal = reapplyStatus === "suspended";
|
||||
|
||||
// Longest matching href wins. A plain prefix test would light up every
|
||||
// ancestor: with a "/shipping-line" home item alongside "/shipping-line/
|
||||
// bookings", Home would stay highlighted on every page beneath it. Exact
|
||||
// matches still win outright, so customer routes are unaffected — their
|
||||
// sidebar hrefs are siblings, never nested inside one another.
|
||||
const bestMatchHref = sidebarItems
|
||||
.flatMap((item) => [item, ...(item.children ?? [])])
|
||||
.map((item) => item.href.toLowerCase())
|
||||
.filter((href) => activePath === href || activePath.startsWith(href + "/"))
|
||||
.sort((a, b) => b.length - a.length)[0];
|
||||
|
||||
const isItemActive = (item: SidebarItem) =>
|
||||
activePath === item.href.toLowerCase() ||
|
||||
activePath.startsWith(item.href.toLowerCase() + "/");
|
||||
bestMatchHref === item.href.toLowerCase();
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
@@ -371,7 +378,9 @@ export function AppLayout({
|
||||
onClick={() =>
|
||||
openServiceModal(p.type as ServiceType, p)
|
||||
}
|
||||
leftSection={<RefreshCw size={15} strokeWidth={1.8} />}
|
||||
leftSection={
|
||||
<RefreshCw size={15} strokeWidth={1.8} />
|
||||
}
|
||||
>
|
||||
{serviceLabel(p.type as ServiceType)}
|
||||
</Menu.Item>
|
||||
@@ -893,7 +902,9 @@ export function AppLayout({
|
||||
</Alert>
|
||||
)}
|
||||
<FileInput
|
||||
label={reapplyId ? "Business license (optional)" : "Business license"}
|
||||
label={
|
||||
reapplyId ? "Business license (optional)" : "Business license"
|
||||
}
|
||||
multiple
|
||||
clearable
|
||||
accept="application/pdf,image/png,image/jpeg"
|
||||
|
||||
@@ -162,7 +162,15 @@ export default function OnboardingResumeBanner({
|
||||
* Self-hides when there's nothing outstanding.
|
||||
*/
|
||||
export function AccountReviewBanner() {
|
||||
const { company, companyStatus, reviewStatus, reviewNote } = useAuth();
|
||||
const { company, companyStatus, reviewStatus, reviewNote, isShippingLine } =
|
||||
useAuth();
|
||||
|
||||
// Shipping lines have no company approval, no operational profiles and no
|
||||
// profile-edit review — every branch below is about customer state they do
|
||||
// not have. Bail explicitly rather than relying on each check happening to
|
||||
// fall through.
|
||||
if (isShippingLine) return null;
|
||||
|
||||
const profiles = company?.company?.companyProfiles ?? [];
|
||||
const pending = profiles.filter((p) => p.status === "pending");
|
||||
const approved = profiles.filter((p) => p.status === "active");
|
||||
|
||||
Reference in New Issue
Block a user