|
|
|
@@ -1,6 +1,6 @@ |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import React, { useState } from "react"; |
|
|
|
import React, { useRef, useState } from "react"; |
|
|
|
import { Box, Button, Paper, Stack, Tab, Tabs, TextField, Typography } from "@mui/material"; |
|
|
|
import { NEXT_PUBLIC_API_URL } from "@/config/api"; |
|
|
|
import { clientAuthFetch } from "@/app/utils/clientAuthFetch"; |
|
|
|
@@ -32,20 +32,30 @@ export default function M18SynPage() { |
|
|
|
const [m18PoCode, setM18PoCode] = useState(""); |
|
|
|
const [isSyncingM18Po, setIsSyncingM18Po] = useState(false); |
|
|
|
const [m18PoSyncResult, setM18PoSyncResult] = useState<string>(""); |
|
|
|
const m18PoInFlightRef = useRef(false); |
|
|
|
|
|
|
|
const [m18DoCode, setM18DoCode] = useState(""); |
|
|
|
const [isSyncingM18Do, setIsSyncingM18Do] = useState(false); |
|
|
|
const [m18DoSyncResult, setM18DoSyncResult] = useState<string>(""); |
|
|
|
const m18DoInFlightRef = useRef(false); |
|
|
|
|
|
|
|
const [m18DoExtraCode, setM18DoExtraCode] = useState(""); |
|
|
|
const [isSyncingM18DoExtra, setIsSyncingM18DoExtra] = useState(false); |
|
|
|
const [m18DoExtraSyncResult, setM18DoExtraSyncResult] = useState<string>(""); |
|
|
|
const m18DoExtraInFlightRef = useRef(false); |
|
|
|
|
|
|
|
const [m18ProductCode, setM18ProductCode] = useState(""); |
|
|
|
const [isSyncingM18Product, setIsSyncingM18Product] = useState(false); |
|
|
|
const [m18ProductSyncResult, setM18ProductSyncResult] = useState<string>(""); |
|
|
|
const m18ProductInFlightRef = useRef(false); |
|
|
|
|
|
|
|
const handleSyncM18PoByCode = async () => { |
|
|
|
if (m18PoInFlightRef.current) return; |
|
|
|
if (!m18PoCode.trim()) { |
|
|
|
alert("Please enter PO code."); |
|
|
|
return; |
|
|
|
} |
|
|
|
m18PoInFlightRef.current = true; |
|
|
|
setIsSyncingM18Po(true); |
|
|
|
setM18PoSyncResult(""); |
|
|
|
try { |
|
|
|
@@ -64,14 +74,17 @@ export default function M18SynPage() { |
|
|
|
alert("M18 PO sync failed. Check console/network."); |
|
|
|
} finally { |
|
|
|
setIsSyncingM18Po(false); |
|
|
|
m18PoInFlightRef.current = false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const handleSyncM18DoByCode = async () => { |
|
|
|
if (m18DoInFlightRef.current) return; |
|
|
|
if (!m18DoCode.trim()) { |
|
|
|
alert("Please enter DO / shop PO code."); |
|
|
|
return; |
|
|
|
} |
|
|
|
m18DoInFlightRef.current = true; |
|
|
|
setIsSyncingM18Do(true); |
|
|
|
setM18DoSyncResult(""); |
|
|
|
try { |
|
|
|
@@ -90,14 +103,47 @@ export default function M18SynPage() { |
|
|
|
alert("M18 DO sync failed. Check console/network."); |
|
|
|
} finally { |
|
|
|
setIsSyncingM18Do(false); |
|
|
|
m18DoInFlightRef.current = false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** DO(加單):M18 搜尋需含備註「(加單)」,本地 isEtra = true */ |
|
|
|
const handleSyncM18DoExtraByCode = async () => { |
|
|
|
if (m18DoExtraInFlightRef.current) return; |
|
|
|
if (!m18DoExtraCode.trim()) { |
|
|
|
alert("Please enter DO / shop PO code (加單)."); |
|
|
|
return; |
|
|
|
} |
|
|
|
m18DoExtraInFlightRef.current = true; |
|
|
|
setIsSyncingM18DoExtra(true); |
|
|
|
setM18DoExtraSyncResult(""); |
|
|
|
try { |
|
|
|
const response = await clientAuthFetch( |
|
|
|
`${NEXT_PUBLIC_API_URL}/m18/test/do-by-code-extra?code=${encodeURIComponent(m18DoExtraCode.trim())}`, |
|
|
|
{ method: "GET" }, |
|
|
|
); |
|
|
|
if (response.status === 401 || response.status === 403) return; |
|
|
|
const text = await response.text(); |
|
|
|
setM18DoExtraSyncResult(text); |
|
|
|
if (!response.ok) { |
|
|
|
alert(`Sync failed: ${response.status}`); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
console.error("M18 DO (加單) Sync By Code Error:", e); |
|
|
|
alert("M18 DO (加單) sync failed. Check console/network."); |
|
|
|
} finally { |
|
|
|
setIsSyncingM18DoExtra(false); |
|
|
|
m18DoExtraInFlightRef.current = false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const handleSyncM18ProductByCode = async () => { |
|
|
|
if (m18ProductInFlightRef.current) return; |
|
|
|
if (!m18ProductCode.trim()) { |
|
|
|
alert("Please enter M18 item / product code."); |
|
|
|
return; |
|
|
|
} |
|
|
|
m18ProductInFlightRef.current = true; |
|
|
|
setIsSyncingM18Product(true); |
|
|
|
setM18ProductSyncResult(""); |
|
|
|
try { |
|
|
|
@@ -116,6 +162,7 @@ export default function M18SynPage() { |
|
|
|
alert("M18 product sync failed. Check console/network."); |
|
|
|
} finally { |
|
|
|
setIsSyncingM18Product(false); |
|
|
|
m18ProductInFlightRef.current = false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
@@ -140,7 +187,8 @@ export default function M18SynPage() { |
|
|
|
<Tabs value={tabValue} onChange={(_, v) => setTabValue(v)} aria-label="M18 sync by code" centered variant="fullWidth"> |
|
|
|
<Tab label="1. PO" id="m18syn-tab-0" /> |
|
|
|
<Tab label="2. DO" id="m18syn-tab-1" /> |
|
|
|
<Tab label="3. Product" id="m18syn-tab-2" /> |
|
|
|
<Tab label="3. DO (加單)" id="m18syn-tab-2" /> |
|
|
|
<Tab label="4. Product" id="m18syn-tab-3" /> |
|
|
|
</Tabs> |
|
|
|
|
|
|
|
<TabPanel value={tabValue} index={0}> |
|
|
|
@@ -202,6 +250,43 @@ export default function M18SynPage() { |
|
|
|
</TabPanel> |
|
|
|
|
|
|
|
<TabPanel value={tabValue} index={2}> |
|
|
|
<Section title="M18 Delivery Order — 加單 (備註含「(加單)」,isEtra)"> |
|
|
|
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}> |
|
|
|
與「2. DO」相同以單號從 M18 同步 shop PO/送貨單,但 M18 列表條件會限制備註含「(加單)」;同步寫入之 delivery_order.isEtra = true。 |
|
|
|
</Typography> |
|
|
|
<Stack direction="row" spacing={2} sx={{ mb: 2, alignItems: "center", flexWrap: "wrap" }}> |
|
|
|
<TextField |
|
|
|
size="small" |
|
|
|
label="DO / Shop PO Code(加單)" |
|
|
|
value={m18DoExtraCode} |
|
|
|
onChange={(e) => setM18DoExtraCode(e.target.value)} |
|
|
|
placeholder="e.g. 與一般 DO 相同單號,但須為加單單據" |
|
|
|
sx={{ minWidth: 320 }} |
|
|
|
/> |
|
|
|
<Button |
|
|
|
variant="contained" |
|
|
|
color="primary" |
|
|
|
onClick={handleSyncM18DoExtraByCode} |
|
|
|
disabled={isSyncingM18DoExtra} |
|
|
|
> |
|
|
|
{isSyncingM18DoExtra ? "Syncing..." : "Sync DO(加單)from M18"} |
|
|
|
</Button> |
|
|
|
</Stack> |
|
|
|
{m18DoExtraSyncResult ? ( |
|
|
|
<TextField |
|
|
|
fullWidth |
|
|
|
multiline |
|
|
|
minRows={4} |
|
|
|
margin="normal" |
|
|
|
label="Sync Result" |
|
|
|
value={m18DoExtraSyncResult} |
|
|
|
InputProps={{ readOnly: true }} |
|
|
|
/> |
|
|
|
) : null} |
|
|
|
</Section> |
|
|
|
</TabPanel> |
|
|
|
|
|
|
|
<TabPanel value={tabValue} index={3}> |
|
|
|
<Section title="M18 Product / material — sync by code"> |
|
|
|
<Stack direction="row" spacing={2} sx={{ mb: 2, alignItems: "center" }}> |
|
|
|
<TextField |
|
|
|
@@ -234,6 +319,7 @@ export default function M18SynPage() { |
|
|
|
) : null} |
|
|
|
</Section> |
|
|
|
</TabPanel> |
|
|
|
|
|
|
|
</Box> |
|
|
|
); |
|
|
|
} |