mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 04:33:11 +00:00
fix(ui): align shared board plumbing with ky v2 and react-router
- api.ts: use ky v2 hook object args, prefix (not prefixUrl), and normalizeApiRequestError - replace react-router-dom with react-router in layout, topbar, and vendor-pos view - move MUI style props (justifyContent, alignItems, flexWrap, display, fontWeight) into sx - resource-list-table/query-key: use local types instead of missing work-order-list module
This commit is contained in:
parent
01939cbb70
commit
a3e8a533b1
10 changed files with 32 additions and 35 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import ky, { type HTTPError, type KyInstance, type Options } from "ky";
|
||||
import ky, { type KyInstance, type Options } from "ky";
|
||||
import { env } from "@/lib/env";
|
||||
import { resolveApiPrefixUrl } from "@/lib/resolve-api-prefix-url";
|
||||
import { API_PATHS } from "@/api/api-paths";
|
||||
import { createApiErrorFromResponse, mapHttpStatusToMessage } from "@/api/api-error";
|
||||
import { mapHttpStatusToMessage, normalizeApiRequestError } from "@/api/api-error";
|
||||
import { queryKeys } from "@/infra/query-key/query-key";
|
||||
import queryClient from "@/lib/query/query-client";
|
||||
import { isAuthBypassEnabled } from "@/lib/auth/auth-bypass";
|
||||
|
|
@ -22,36 +22,23 @@ function isAuthLoginRequest(request: Request): boolean {
|
|||
}
|
||||
|
||||
export const api: KyInstance = ky.create({
|
||||
prefixUrl: resolveApiPrefixUrl(env.apiUrl),
|
||||
prefix: resolveApiPrefixUrl(env.apiUrl),
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
(request) => {
|
||||
({ request }) => {
|
||||
const token = getAccessToken();
|
||||
if (token) {
|
||||
request.headers.set("Authorization", token);
|
||||
}
|
||||
},
|
||||
],
|
||||
beforeError: [
|
||||
async (error: HTTPError) => {
|
||||
const { response } = error;
|
||||
|
||||
if (!response) {
|
||||
error.message = "No response from server. Please check your connection.";
|
||||
return error;
|
||||
}
|
||||
|
||||
const apiError = await createApiErrorFromResponse(response);
|
||||
error.message = apiError.message;
|
||||
return error;
|
||||
},
|
||||
],
|
||||
beforeError: [({ error }) => normalizeApiRequestError(error)],
|
||||
afterResponse: [
|
||||
async (request, _options, response) => {
|
||||
({ request, response }) => {
|
||||
if (response.status !== 401 || isAuthLoginRequest(request) || isAuthBypassEnabled()) {
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { Outlet } from "react-router";
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
import { ProtectedRoute } from "@/components/auth/protected-route";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, type ReactNode } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
|
|
@ -33,7 +33,7 @@ function formatMoney(value: number | null | undefined): string {
|
|||
function InfoRow({ label, children }: { label: string; children: ReactNode }) {
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary" display="block">
|
||||
<Typography variant="caption" color="text.secondary" sx={{ display: "block" }}>
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
|
|
@ -107,7 +107,11 @@ export default function VendorPoViewPage() {
|
|||
|
||||
return (
|
||||
<Box className="mx-auto max-w-5xl p-4">
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" className="mb-4">
|
||||
<Stack
|
||||
direction="row"
|
||||
className="mb-4"
|
||||
sx={{ justifyContent: "space-between", alignItems: "center" }}
|
||||
>
|
||||
<Button variant="text" onClick={() => navigate(-1)}>
|
||||
← Back
|
||||
</Button>
|
||||
|
|
@ -118,7 +122,7 @@ export default function VendorPoViewPage() {
|
|||
|
||||
<Stack spacing={1} className="mb-4">
|
||||
<Typography variant="h5">{dispatch.poNumber || "(no PO #)"}</Typography>
|
||||
<Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: "center", flexWrap: "wrap" }}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Dispatch {dispatch.dispatchNumber || "—"}
|
||||
</Typography>
|
||||
|
|
@ -256,7 +260,10 @@ export default function VendorPoViewPage() {
|
|||
<Stack spacing={2}>
|
||||
{dispatch.upliftRequests.map((u) => (
|
||||
<Box key={String(u.id)} className="rounded border border-border p-3">
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{ justifyContent: "space-between", alignItems: "center" }}
|
||||
>
|
||||
<Typography variant="body2" className="font-semibold">
|
||||
{formatMoney(u.currentNTE)} → {formatMoney(u.requestedNTE)}
|
||||
<Typography
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function CommentTimeline({
|
|||
<Stack spacing={2} className={`${maxHeightClass} overflow-y-auto`}>
|
||||
{sorted.map((item) => (
|
||||
<Box key={String(item.id)} className="rounded border border-border p-3">
|
||||
<Stack direction="row" justifyContent="space-between" className="mb-1">
|
||||
<Stack direction="row" className="mb-1" sx={{ justifyContent: "space-between" }}>
|
||||
<Typography variant="caption" className="font-semibold">
|
||||
{item.author}
|
||||
</Typography>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export function DetailField({ label, value, className, highlight }: DetailFieldP
|
|||
|
||||
return (
|
||||
<Box className={className}>
|
||||
<Typography variant="caption" color="text.secondary" display="block">
|
||||
<Typography variant="caption" color="text.secondary" sx={{ display: "block" }}>
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography variant="body2" className={colorClass}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate } from "react-router";
|
||||
import LogoutOutlinedIcon from "@mui/icons-material/LogoutOutlined";
|
||||
import SettingsOutlinedIcon from "@mui/icons-material/SettingsOutlined";
|
||||
import {
|
||||
|
|
@ -199,7 +199,7 @@ export function AppTopbar({ onToggleNav }: AppTopbarProps) {
|
|||
{userInitials}
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography variant="body2" fontWeight={600}>
|
||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||
{user?.fullname || "User"}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
|
|
|
|||
|
|
@ -24,13 +24,15 @@ export function PageHeader({
|
|||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
className={cn(
|
||||
surface &&
|
||||
"-mx-2.5 -mt-2.5 shrink-0 border-b border-(--color-border) bg-(--color-bg-surface) px-5 py-4",
|
||||
className,
|
||||
)}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Stack spacing={0}>
|
||||
{eyebrow && (
|
||||
|
|
@ -53,7 +55,7 @@ export function PageHeader({
|
|||
)}
|
||||
</Stack>
|
||||
{actions && (
|
||||
<Stack direction="row" spacing={1} alignItems="center" flexWrap="nowrap">
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: "center", flexWrap: "nowrap" }}>
|
||||
{actions}
|
||||
</Stack>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import {
|
|||
TableRow,
|
||||
} from "@mui/material";
|
||||
import { TableEmptyRow, TableLoadingRow } from "@/components/ui/table-state-rows";
|
||||
import type { SortDirection } from "@/domain/work-orders/types/work-order-list";
|
||||
|
||||
export type SortDirection = "asc" | "desc" | "";
|
||||
|
||||
export type ResourceListColumn<T> = {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function StatusChipFilter({
|
|||
return (
|
||||
<div>
|
||||
<span className="mb-1 block text-[11px] font-semibold text-muted-foreground">{label}</span>
|
||||
<Stack direction="row" spacing={0.75} flexWrap="wrap" useFlexGap>
|
||||
<Stack direction="row" spacing={0.75} useFlexGap sx={{ flexWrap: "wrap" }}>
|
||||
<Chip
|
||||
label="All"
|
||||
size="small"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { WorkOrdersListParams } from "@/domain/work-orders/types/work-order-list";
|
||||
type WorkOrdersListParams = Record<string, unknown>;
|
||||
|
||||
export const queryKeys = {
|
||||
auth: {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue