Kaynağa Gözat

update

master
cyril.tsui 2 hafta önce
ebeveyn
işleme
63730ebbe6
6 değiştirilmiş dosya ile 120 ekleme ve 210 silme
  1. +2
    -0
      package.json
  2. +2
    -2
      src/components/PoDetail/EscalationComponent.tsx
  3. +54
    -189
      src/components/PoDetail/EscalationLog.tsx
  4. +23
    -0
      src/components/PoDetail/EscalationTab.tsx
  5. +15
    -7
      src/theme/devias-material-kit/components.ts
  6. +24
    -12
      src/theme/devias-material-kit/typography.ts

+ 2
- 0
package.json Dosyayı Görüntüle

@@ -20,6 +20,7 @@
"@mui/material-nextjs": "^5.15.0",
"@mui/x-data-grid": "^6.18.7",
"@mui/x-date-pickers": "^6.18.7",
"@tanstack/react-table": "^8.21.3",
"@tiptap/core": "^2.14.0",
"@tiptap/extension-color": "^2.14.0",
"@tiptap/extension-document": "^2.14.0",
@@ -46,6 +47,7 @@
"i18next": "^23.7.11",
"i18next-resources-to-backend": "^1.2.0",
"lodash": "^4.17.21",
"lucide-react": "^0.536.0",
"mui-color-input": "^7.0.0",
"next": "14.0.4",
"next-auth": "^4.24.5",


+ 2
- 2
src/components/PoDetail/EscalationComponent.tsx Dosyayı Görüntüle

@@ -30,7 +30,7 @@ interface FormData {
message: string;
}

function CollapsibleSelectForm(): JSX.Element {
function EscalationComponent(): JSX.Element {
const [isCollapsed, setIsCollapsed] = useState<boolean>(false);
const [formData, setFormData] = useState<FormData>({
name: '',
@@ -162,4 +162,4 @@ function CollapsibleSelectForm(): JSX.Element {
);
}

export default CollapsibleSelectForm;
export default EscalationComponent;

+ 54
- 189
src/components/PoDetail/EscalationLog.tsx Dosyayı Görüntüle

@@ -112,160 +112,58 @@ function QCReportForm({ reports }: QCReportFormProps): JSX.Element {

return (
<Box sx={{ maxWidth: '1200px', mx: 'auto', p: 3 }}>
{/* Title */}
{/* <Box sx={{ mb: 4 }}>
<Typography variant="h5" fontWeight="bold" color="text.primary">
品質控制上報系統
{/* Table Section */}
<Box>
<Typography variant="h6" fontWeight="medium" sx={{ mb: 2 }}>
上報資料
</Typography>
<Typography variant="body2" color="text.secondary">
品質檢測結果上報與管理
</Typography>
</Box> */}

{/* <Box sx={{ display: 'grid', gridTemplateColumns: { xs: '1fr', lg: '2fr 1fr' }, gap: 3 }}> */}
<Box sx={{ display: 'grid' }}>
{/* Table Section */}
<Box>
<Typography variant="h6" fontWeight="medium" sx={{ mb: 2 }}>
上報資料
</Typography>
<TableContainer component={Paper} elevation={2}>
<Table>
<TableHead sx={{ bgcolor: 'grey.50' }}>
{table.getHeaderGroups().map(headerGroup => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map(header => (
<TableCell
key={header.id}
sx={{
fontSize: '0.75rem',
fontWeight: 'medium',
color: 'text.secondary',
textTransform: 'uppercase',
py: 2,
px: 3,
}}
>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableHead>
<TableBody>
{table.getRowModel().rows.map(row => (
<TableRow
key={row.id}
onClick={() => handleReportClick(row.original)}
sx={{
cursor: 'pointer',
'&:hover': { bgcolor: 'grey.50' },
bgcolor: selectedReport?.id === row.original.id ? 'primary.light' : 'inherit',
transition: 'background-color 0.15s',
}}
>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id} sx={{ py: 2, px: 3 }}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>

{/* Details Section */}
{/* <Box>
<Typography variant="h6" fontWeight="medium" sx={{ mb: 2 }}>
詳細資訊
</Typography>
<Card elevation={2} sx={{ minHeight: '300px', bgcolor: 'grey.50' }}>
<CardContent>
{selectedReport ? (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, color: 'primary.main', mb: 2 }}>
<DescriptionIcon />
<Typography variant="subtitle1" fontWeight="medium">
上報詳情
</Typography>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium">
產品名稱:
</Typography>
<Typography variant="body2">{selectedReport.productName}</Typography>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium">
檢測結果:
</Typography>
<Box sx={{ mt: 1 }}>{getQualifiedStatus(selectedReport.isQualified)}</Box>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium">
批次號碼:
</Typography>
<Typography variant="body2">{selectedReport.batchNumber}</Typography>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium">
檢驗員:
</Typography>
<Typography variant="body2">{selectedReport.inspector}</Typography>
</Box>

<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<CalendarTodayIcon fontSize="small" sx={{ color: 'text.secondary' }} />
<Typography variant="body2">
上報日期:{selectedReport.reportDate}
</Typography>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium" sx={{ mb: 1 }}>
檢測規格:
</Typography>
<Paper sx={{ p: 1, bgcolor: 'background.paper' }}>
<Typography variant="body2">{selectedReport.specifications}</Typography>
</Paper>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium" sx={{ mb: 1 }}>
檢測結果詳情:
</Typography>
<Paper sx={{ p: 1, bgcolor: 'background.paper' }}>
<Typography variant="body2">{selectedReport.testResults}</Typography>
</Paper>
</Box>

<Box>
<Typography variant="body2" color="text.secondary" fontWeight="medium" sx={{ mb: 1 }}>
備註 (REMARKS):
</Typography>
<Paper sx={{ p: 1, bgcolor: 'background.paper' }}>
<Typography variant="body2">{selectedReport.remarks}</Typography>
</Paper>
</Box>
</Box>
) : (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
<Typography variant="body2" color="text.secondary">
請點擊表格中的記錄來查看詳細資訊
</Typography>
</Box>
)}
</CardContent>
</Card>
</Box> */}
<TableContainer component={Paper} elevation={2}>
<Table>
<TableHead sx={{ bgcolor: 'grey.50' }}>
{table.getHeaderGroups().map(headerGroup => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map(header => (
<TableCell
key={header.id}
sx={{
fontSize: '0.75rem',
fontWeight: 'medium',
color: 'text.secondary',
textTransform: 'uppercase',
py: 2,
px: 3,
}}
>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableHead>
<TableBody>
{table.getRowModel().rows.map(row => (
<TableRow
key={row.id}
onClick={() => handleReportClick(row.original)}
sx={{
cursor: 'pointer',
'&:hover': { bgcolor: 'grey.50' },
bgcolor: selectedReport?.id === row.original.id ? 'primary.light' : 'inherit',
transition: 'background-color 0.15s',
}}
>
{row.getVisibleCells().map(cell => (
<TableCell key={cell.id} sx={{ py: 2, px: 3 }}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
</Box>
);
@@ -273,19 +171,8 @@ function QCReportForm({ reports }: QCReportFormProps): JSX.Element {

// Dummy data
const dummyReports = [
// {
// id: '1',
// productName: '智慧手機 Pro Max',
// isQualified: true,
// remarks: '所有檢測項目均符合標準規格',
// reportDate: '2024-08-07',
// batchNumber: 'SPM-240807-001',
// inspector: '張品質',
// testResults: '外觀檢查:無瑕疵,功能測試:100%通過,性能測試:符合標準',
// specifications: '螢幕解析度≥1080p,電池續航≥24小時,防水等級IPX7',
// },
{
id: '2',
id: '1',
productName: '無線藍牙耳機',
isQualified: false,
remarks: '包裝有破損',
@@ -296,7 +183,7 @@ const dummyReports = [
specifications: '頻響範圍20Hz-20kHz,左右聲道音量差≤1dB,電池續航≥8小時',
},
{
id: '3',
id: '2',
productName: '筆記型電腦',
isQualified: true,
remarks: '經檢查,無損壞',
@@ -306,32 +193,10 @@ const dummyReports = [
testResults: '溫度測試:CPU最高溫度75°C,性能測試:符合預期',
specifications: 'CPU溫度≤85°C,開機時間≤30秒,電池續航≥6小時',
},
// {
// id: '4',
// productName: '智慧手錶',
// isQualified: false,
// remarks: '防水測試未通過,密封性能不足',
// reportDate: '2024-08-04',
// batchNumber: 'SW-240804-004',
// inspector: '劉品管',
// testResults: '防水測試:IPX5等級測試失敗,發現進水現象',
// specifications: '防水等級≥IPX7,電池續航≥48小時,心率監測精度≥95%',
// },
// {
// id: '5',
// productName: '平板電腦',
// isQualified: true,
// remarks: '觸控靈敏度優良,顯示效果佳',
// reportDate: '2024-08-03',
// batchNumber: 'TB-240803-005',
// inspector: '陳測試',
// testResults: '觸控測試:反應時間<10ms,顯示測試:色彩準確度98%',
// specifications: '螢幕尺寸10.1吋,解析度2K,觸控反應時間≤15ms',
// },
];

// Main component
const EscalationLog: React.FC = () => {
function EscalationLog(): JSX.Element {
return <QCReportForm reports={dummyReports} />;
};


+ 23
- 0
src/components/PoDetail/EscalationTab.tsx Dosyayı Görüntüle

@@ -0,0 +1,23 @@
import StockInForm from "./StockInForm";
import EscalationLog from "./EscalationLog";
import EscalationComponent from "./EscalationComponent";
import React from "react";
import { PurchaseQcResult } from "@/app/api/po/actions";
import { StockInLine } from "@/app/api/po";

interface Props {
itemDetail: StockInLine & {
qcResult?: PurchaseQcResult[] | undefined;
};
disabled: boolean
}

const EscalationTab:React.FC<Props> = ({itemDetail, disabled}) => {
return <>
<StockInForm itemDetail={itemDetail} disabled={disabled}/>
<EscalationLog/>
<EscalationComponent/>
</>
};

export default EscalationTab;

+ 15
- 7
src/theme/devias-material-kit/components.ts Dosyayı Görüntüle

@@ -2,6 +2,7 @@ import { ThemeOptions, createTheme } from "@mui/material";
import palette from "./palette";

// Used only to create transitions
const defaultFontSize = 18;
const muiTheme = createTheme();

const components: ThemeOptions["components"] = {
@@ -15,7 +16,7 @@ const components: ThemeOptions["components"] = {
MuiAvatar: {
styleOverrides: {
root: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 600,
letterSpacing: 0,
},
@@ -163,7 +164,7 @@ const components: ThemeOptions["components"] = {
MuiInput: {
styleOverrides: {
input: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 500,
lineHeight: "24px",
"&::placeholder": {
@@ -215,7 +216,7 @@ const components: ThemeOptions["components"] = {
},
},
input: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 500,
lineHeight: "24px",
},
@@ -245,7 +246,7 @@ const components: ThemeOptions["components"] = {
},
},
input: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 500,
lineHeight: "24px",
},
@@ -259,7 +260,7 @@ const components: ThemeOptions["components"] = {
MuiFormLabel: {
styleOverrides: {
root: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 500,
[`&.MuiInputLabel-filled`]: {
transform: "translate(12px, 18px) scale(1)",
@@ -283,7 +284,7 @@ const components: ThemeOptions["components"] = {
MuiTab: {
styleOverrides: {
root: {
fontSize: 14,
fontSize: defaultFontSize,
fontWeight: 500,
lineHeight: 1.71,
minWidth: "auto",
@@ -297,6 +298,13 @@ const components: ThemeOptions["components"] = {
},
},
},
MuiTableRow: {
styleOverrides: {
root: {
lineHeight: 0.5,
},
},
},
MuiTableCell: {
styleOverrides: {
root: {
@@ -313,7 +321,7 @@ const components: ThemeOptions["components"] = {
borderBottom: "none",
backgroundColor: palette.neutral[50],
color: palette.neutral[700],
fontSize: 12,
fontSize: defaultFontSize - 2,
fontWeight: 600,
lineHeight: 2,
letterSpacing: 0.5,


+ 24
- 12
src/theme/devias-material-kit/typography.ts Dosyayı Görüntüle

@@ -9,12 +9,14 @@ const typography: TypographyOptions = {
fontFamily:
'"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
body1: {
fontSize: "1rem",
// fontSize: "1rem",
fontSize: "1.25rem",
fontWeight: 400,
lineHeight: 1.5,
},
body2: {
fontSize: "0.875rem",
// fontSize: "0.875rem",
fontSize: "1rem",
fontWeight: 400,
lineHeight: 1.57,
},
@@ -22,22 +24,26 @@ const typography: TypographyOptions = {
fontWeight: 600,
},
caption: {
fontSize: "0.75rem",
// fontSize: "0.75rem",
fontSize: "0.875rem",
fontWeight: 500,
lineHeight: 1.66,
},
subtitle1: {
fontSize: "1rem",
// fontSize: "1rem",
fontSize: "1.25rem",
fontWeight: 500,
lineHeight: 1.57,
},
subtitle2: {
fontSize: "0.875rem",
// fontSize: "0.875rem",
fontSize: "1rem",
fontWeight: 500,
lineHeight: 1.57,
},
overline: {
fontSize: "0.75rem",
// fontSize: "0.75rem",
fontSize: "0.875rem",
fontWeight: 600,
letterSpacing: "0.5px",
lineHeight: 2.5,
@@ -46,37 +52,43 @@ const typography: TypographyOptions = {
h1: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "3.5rem",
// fontSize: "3.5rem",
fontSize: "3.75rem",
lineHeight: 1.2,
},
h2: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "3rem",
// fontSize: "3rem",
fontSize: "3.25rem",
lineHeight: 1.2,
},
h3: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "2.25rem",
// fontSize: "2.25rem",
fontSize: "2.5rem",
lineHeight: 1.2,
},
h4: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "2rem",
// fontSize: "2rem",
fontSize: "2.25rem",
lineHeight: 1.2,
},
h5: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "1.5rem",
// fontSize: "1.5rem",
fontSize: "1.75rem",
lineHeight: 1.2,
},
h6: {
fontFamily: "'Plus Jakarta Sans', sans-serif",
fontWeight: 700,
fontSize: "1.125rem",
// fontSize: "1.125rem",
fontSize: "1.25rem",
lineHeight: 1.2,
},
};


Yükleniyor…
İptal
Kaydet