liuxf 3 月之前
父节点
当前提交
6199d36155
共有 5 个文件被更改,包括 966 次插入0 次删除
  1. 二进制
      public/base.png
  2. 二进制
      public/partner.png
  3. 1 0
      public/return.svg
  4. 155 0
      src/pages/Base/Order/DateChangeDialog.tsx
  5. 810 0
      src/pages/Base/Order/index.tsx

二进制
public/base.png


二进制
public/partner.png


文件差异内容过多而无法显示
+ 1 - 0
public/return.svg


+ 155 - 0
src/pages/Base/Order/DateChangeDialog.tsx

@@ -0,0 +1,155 @@
+import React, { useState, useEffect, useRef } from "react";
+
+// 定义组件 props 类型
+interface DateChangeDialogProps {
+  show: boolean; // 控制对话框显示/隐藏
+  onClose: () => void; // 关闭对话框的回调
+  onConfirm: (reason: string, changeValue: string) => void; // 确认变更的回调
+  reasonOptions: string[]; // 事由选项列表
+}
+
+const DateChangeDialog: React.FC<DateChangeDialogProps> = ({
+  show,
+  onClose,
+  onConfirm,
+  reasonOptions,
+}) => {
+  // 组件内部维护输入状态
+  const [selectedReason, setSelectedReason] = useState("");
+  const [changeValue, setChangeValue] = useState("");
+  const reasonSelectRef = useRef<HTMLSelectElement>(null);
+
+  // 组件挂载时添加样式
+  useEffect(() => {
+    const style = document.createElement('style');
+    style.id = 'date-change-dialog-styles';
+    style.textContent = `
+      .custom-dialog {
+        position: fixed;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        padding: 20px;
+        background: white;
+        border: 1px solid #ccc;
+        border-radius: 5px;
+        box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+        z-index: 1000;
+        width: 300px;
+      }
+      .dialog-overlay {
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background: rgba(0,0,0,0.5);
+        z-index: 999;
+      }
+      .dialog-group {
+        margin-bottom: 15px;
+      }
+      .dialog-group select,
+      .dialog-group input {
+        width: 100%;
+        padding: 8px;
+        box-sizing: border-box;
+      }
+      .dialog-row {
+        display: flex;
+        align-items: center;
+        gap: 10px;
+      }
+      .dialog-label {
+        width: 60px;
+        margin-bottom: 0;
+      }
+      .dialog-select,
+      .dialog-input {
+        flex: 1;
+        width: auto;
+      }
+    `;
+    document.head.appendChild(style);
+
+    return () => {
+      // 组件卸载时移除样式
+      const styleElement = document.getElementById('date-change-dialog-styles');
+      if (styleElement) {
+        document.head.removeChild(styleElement);
+      }
+    };
+  }, []);
+
+  useEffect(() => {
+    // 当对话框从显示变为隐藏时,重置状态
+    if (!show) {
+      setSelectedReason("");
+      setChangeValue("");
+    } else if (reasonSelectRef.current) {
+      // 当对话框显示时聚焦到下拉框
+      reasonSelectRef.current.focus();
+    }
+  }, [show]);
+
+  // 处理回车键逻辑
+  const handleKeyDown = (e: React.KeyboardEvent) => {
+    if (e.key === "Enter") {
+      if (selectedReason && changeValue) {
+        handleConfirm();
+      } else {
+        onClose();
+      }
+    }
+  };
+
+  // 处理确认按钮逻辑
+  const handleConfirm = () => {
+    if (selectedReason && changeValue) {
+      onConfirm(selectedReason, changeValue); // 将输入值传递给父组件
+      onClose(); // 关闭对话框
+    }
+  };
+
+  // 未显示时不渲染
+  if (!show) return null;
+
+  return (
+    <>
+      {/* 遮罩层,点击关闭对话框 */}
+      <div className="dialog-overlay" onClick={onClose} />
+      {/* 对话框主体 */}
+      <div className="custom-dialog">
+        <div className="dialog-group dialog-row">
+          <label className="dialog-label">事由</label>
+          <select
+            ref={reasonSelectRef}
+            value={selectedReason}
+            onChange={(e) => setSelectedReason(e.target.value)}
+            onKeyDown={handleKeyDown}
+            className="dialog-select"
+          >
+            <option value="">選択してください</option>
+            {reasonOptions.map((option) => (
+              <option key={option} value={option}>
+                {option}
+              </option>
+            ))}
+          </select>
+        </div>
+        <div className="dialog-group dialog-row">
+          <label className="dialog-label">変更後</label>
+          <input
+            type="text"
+            value={changeValue}
+            onChange={(e) => setChangeValue(e.target.value)}
+            onKeyDown={handleKeyDown}
+            className="dialog-input"
+          />
+        </div>
+      </div>
+    </>
+  );
+};
+
+export default DateChangeDialog;

+ 810 - 0
src/pages/Base/Order/index.tsx

@@ -0,0 +1,810 @@
+"use client";
+
+import React, { useMemo, useState, useEffect } from "react";
+import { AgGridReact } from "ag-grid-react";
+import {
+    ClientSideRowModelModule,
+    ColDef,
+    ColGroupDef,
+    ModuleRegistry,
+    ValidationModule,
+    ICellRendererParams,
+    CellClassParams,
+    ValueFormatterParams,
+    CellClickedEvent,
+    ISelectCellEditorParams,
+    SelectEditorModule,
+    CellStyleModule
+} from "ag-grid-community";
+import "ag-grid-community/styles/ag-theme-alpine.css";
+import DateChangeDialog from "./DateChangeDialog";
+import Chat from "./Chat";
+
+// 注册必要的模块
+ModuleRegistry.registerModules([
+    ClientSideRowModelModule,
+    SelectEditorModule,
+    CellStyleModule,
+    ...(process.env.NODE_ENV!== "production"? [ValidationModule] : [])
+]);
+
+// 支店选项
+const branchOptions = [
+    "東京支店",
+    "神奈川支店",
+    "品川営業所",
+    "札幌支店",
+    "福岡支店"
+];
+
+// 事由选项
+const reasonOptions = [
+    "臨時変更",
+    "計画変更",
+    "休日調整",
+    "その他"
+];
+
+const orderInfo = {
+    deliveryPartner: {
+        id: "0311111111",
+        name: "AAA株式会社"
+    },
+    status: {
+        companyCode: "R000001",
+        status: "全承諾",
+        version: 1,
+        instructionDate: "2025/6/25",
+        approvalDate: "2025/6/25"
+    },
+    monthlyInstruction: {
+        versionOptions: ["ver-1", "ver-2", "ver-3", "ver-4", "ver-5"],
+        selectedVersion: "ver-1"
+    }
+};
+
+const historyData = [
+    {
+        type: '履歴',
+        date: '2025/06/16 10:00',
+        action: '指示書生成'
+    },
+    {
+        type: '履歴',
+        date: '2025/06/16 15:24',
+        action: '指示書編集'
+    },
+    {
+        type: '履歴',
+        date: '2025/06/16 15:24',
+        action: '指示書送付'
+    }
+];
+
+const weekTexts = ["火", "水", "木", "金", "土", "日", "月"];
+
+const GridExample = () => {
+    const containerStyle = useMemo(() => ({ width: "100%" }), []);
+    const gridStyle = useMemo(() => ({ width: "100%" }), []);
+    const [rowData, setRowData] = useState(initializeRowData());
+    const [showDialog, setShowDialog] = useState(false);
+    const [modifiedCells, setModifiedCells] = useState<Set<string>>(new Set());
+    const [selectedCell, setSelectedCell] = useState<{rowIndex: number | null, colId: string, currentValue: string} | null>(null);
+    const [cellReasons, setCellReasons] = useState<Record<string, string>>({});
+    const [showChat, setShowChat] = useState(false); // 控制聊天侧边栏显示的状态
+
+    // 初始化样式
+    useEffect(() => {
+        const style = document.createElement('style');
+        style.textContent = `
+      .ag-theme-alpine .header-center .ag-header-cell-label {
+        justify-content: center !important;
+        text-align: center !important;
+      }
+
+      .ag-theme-alpine .header-center.ag-header-group-cell {
+        text-align: center !important;
+      }
+
+      .ag-theme-alpine .header-center.ag-header-group-cell .ag-header-group-cell-label {
+        justify-content: center !important;
+        display: flex !important;
+        width: 100% !important;
+      }
+
+      // .order-info-container {
+      //   margin-bottom: 20px;
+      //   padding: 15px;
+      //   border: 1px solid #dcdcdc;
+      //   border-radius: 4px;
+      // }
+      .order-info-section {
+        margin-bottom: 35px;
+      }
+      .order-info-section h3 {
+        margin: 0 0 5px 0;
+        font-size: 14px;
+        font-weight: bold;
+      }
+      .order-info-row {
+        margin: 10px 0 10px 20px;
+        font-size: 14px;
+      }
+      .status-section {
+        width: 100%;
+        border-collapse: collapse;
+        margin-top: 8px;
+        margin-left: 10px;
+      }
+      .status-section th,
+      .status-section td {
+        padding: 5px 10px;
+        text-align: left;
+        font-size: 14px;
+      }
+
+      .status-section th {
+        font-weight: normal;
+      }
+
+      .version-select-container {
+        display: flex;
+        align-items: center;
+        margin-left: 20px;
+      }
+      .version-select-container label {
+        margin-right: 10px;
+        white-space: nowrap;
+        font-size: 14px;
+      }
+      .version-select-container select {
+        padding: 5px 35px;
+        font-size: 14px;
+        margin-left: 20px;
+        padding-left: 10px;
+      }
+
+      .message-btn {
+        float: right;
+        padding: 7px 50px;
+        background-color: #000;
+        color: #fff;
+        border: none;
+        cursor: pointer;
+        position: relative;
+        top: -17px;
+      }
+      .edit-btn {
+        margin-left: auto;
+        padding: 7px 50px;
+        background-color: #000;
+        color: #fff;
+        border: none;
+        cursor: pointer;
+      }
+      .add-row-btn {
+        background: transparent;
+        border: none;
+        color: #0070c0;
+        cursor: pointer;
+        margin-left: 5px;
+      }
+      .action-btn {
+        background-color: #000;
+        color: #fff;
+        border: none;
+        padding: 7px 20px;
+        cursor: pointer;
+        font-size: 14px;
+      }
+      .history-table-custom {
+        width: 100%;
+        border-collapse: collapse;
+      }
+      .type-td {
+        padding: 5px 20px;
+      }
+      .date-td {
+        padding: 5px 20px;
+      }
+      .action-td {
+        padding: 5px 20px;
+      }
+      .history-title-custom {
+        font-size: 14px;
+        font-weight: bold;
+        margin-bottom: 8px;
+        display: block;
+      }
+      .ag-header-cell-resize {
+       &:after {
+        display: none;
+       }
+      }
+     .ag-theme-alpine .ag-cell {
+       border-right: 1px solid #dcdcdc;
+       text-align: center;
+     }
+     .ag-theme-alpine .ag-header-cell {
+       border-right: 1px solid #dcdcdc;
+     }
+     .line-group-header {
+       border-right: 1px solid #dcdcdc;
+     }
+     .date-group-header {
+       border-right: 1px solid #dcdcdc !important;
+     }
+     .checkbox{
+       display: none;
+     }
+     .tokyoBranchCol{
+       display: none;
+     }
+     .chat-sidebar {
+       position: fixed;
+       top: 0;
+       right: 0;
+       width: 1060px;
+       height: 100vh;
+       background-color: #fff;
+       box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);
+       z-index: 1000;
+       display: flex;
+       flex-direction: column;
+       padding: 20px;
+       box-sizing: border-box;
+       overflow: hidden;
+     }
+     .chat-messages-container {
+       flex: 1;
+       overflow-y: auto;
+       margin-bottom: 16px;
+     }
+     .overlay {
+       position: fixed;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       background-color: rgba(0, 0, 0, 0.5);
+       z-index: 999;
+     }
+    `;
+        document.head.appendChild(style);
+
+        return () => {
+            document.head.removeChild(style);
+        };
+    }, []);
+
+    // 生成1-31的日期列定义
+    const generateDateColumns = () => {
+        const columns: ColGroupDef[] = [];
+        for (let i = 1; i <= 31; i++) {
+            const weekIndex = (i - 1) % weekTexts.length;
+            const colId = `date_${i}`;
+            columns.push({
+                headerName: i.toString(),
+                headerClass: "header-center date-group-header",
+                children: [
+                    {
+                        field: colId,
+                        headerName: weekTexts[weekIndex],
+                        headerClass: "header-center",
+                        width: 55,
+                        cellRenderer: (params: ICellRendererParams) => {
+                            const cellValue = params.value || "";
+                            const rowIndex = params.node.rowIndex;
+                            const cellKey = `${rowIndex}-${colId}`;
+                            const reason = cellReasons[cellKey] || "";
+
+                            return (
+                                <div
+                                    title={reason? `变更理由:${reason}` : ""}
+                                    style={{
+                                        minHeight: '100%',
+                                        width: '100%',
+                                        display: 'flex',
+                                        alignItems: 'center',
+                                        justifyContent: 'center'
+                                    }}
+                                >
+                                    {cellValue}
+                                </div>
+                            );
+                        },
+                        onCellClicked: (params: CellClickedEvent) => {
+                            setSelectedCell({
+                                rowIndex: params.node.rowIndex,
+                                colId: colId,
+                                currentValue: params.value as string
+                            });
+                            setShowDialog(true);
+                        },
+                        cellStyle: (params: CellClassParams) => {
+                            const rowIndex = params.node.rowIndex;
+                            const cellKey = `${rowIndex}-${colId}`;
+                            const isModified = modifiedCells.has(cellKey);
+                            if (isModified) {
+                                return { backgroundColor: '#3a8aca' };
+                            }
+                            return null;
+                        }
+                    }
+                ]
+            });
+        }
+        return columns;
+    };
+
+
+    // 初始化行数据
+    function initializeRowData() {
+        return [
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "025990",
+                "系統": "02",
+                "線便名": "大賀10t①",
+                "入庫場所": "羽田CGB",
+                "入庫時間": "21:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "東京支店",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 3 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "027990",
+                "系統": "23",
+                "線便名": "大賀10t②",
+                "入庫場所": "桜丘",
+                "入庫時間": "19:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "神奈川支店",
+                "approveStatus": "unapproved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 4 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "*",
+                "発": "032990",
+                "着": "027990",
+                "系統": "G8",
+                "線便名": "大賀10t③",
+                "入庫場所": "目黒",
+                "入庫時間": "18:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "品川営業所",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 5 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "027990",
+                "系統": "G9",
+                "線便名": "西大阪交表",
+                "入庫場所": "羽田CGB",
+                "入庫時間": "21:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "札幌支店",
+                "approveStatus": "unapproved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 2 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "061990",
+                "着": "032990",
+                "系統": "06",
+                "線便名": "羽田CG交裏",
+                "入庫場所": "西大阪B",
+                "入庫時間": "19:00",
+                "使用車両(トン)": "10",
+                "checkboxCol": "",
+                "tokyoBranchCol": "福岡支店",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 6 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "032990",
+                "系統": "M8",
+                "線便名": "大賀10t⑥",
+                "入庫場所": "羽田CGB",
+                "入庫時間": "21:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "東京支店",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 3 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "053990",
+                "系統": "06",
+                "線便名": "中部日祝",
+                "入庫場所": "成城",
+                "入庫時間": "19:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "神奈川支店",
+                "approveStatus": "unapproved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 4 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "*",
+                "発": "032990",
+                "着": "027990",
+                "系統": "G8",
+                "線便名": "大賀10t③",
+                "入庫場所": "目黒",
+                "入庫時間": "18:00",
+                "使用車両(トン)": "13",
+                "checkboxCol": "",
+                "tokyoBranchCol": "品川営業所",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 5 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "032990",
+                "着": "132990",
+                "系統": "02",
+                "線便名": "大賀7t",
+                "入庫場所": "八幡山",
+                "入庫時間": "19:00",
+                "使用車両(トン)": "2",
+                "checkboxCol": "",
+                "tokyoBranchCol": "札幌支店",
+                "approveStatus": "unapproved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 2 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+            {
+                "AM": "",
+                "発": "061990",
+                "着": "032990",
+                "系統": "06",
+                "線便名": "羽田CG交裏",
+                "入庫場所": "西大阪B",
+                "入庫時間": "19:00",
+                "使用車両(トン)": "10",
+                "checkboxCol": "",
+                "tokyoBranchCol": "福岡支店",
+                "approveStatus": "approved",
+                ...Array.from({ length: 31 }, (_, i) => ({
+                    [`date_${i + 1}`]: (i + 1) % 6 === 0? "〇" : ""
+                })).reduce((acc, curr) => ({...acc,...curr }), {})
+            },
+        ];
+    }
+
+    // 构建列定义
+    const columnDefs: (ColDef | ColGroupDef)[] = [
+        {
+            field: "checkboxCol",
+            headerName: "",
+            width: 50,
+            cellRenderer: (params: ICellRendererParams) => {
+                return <input type="checkbox" />;
+            },
+            headerClass: "header-center checkbox",
+        },
+        {
+            field: "tokyoBranchCol",
+            headerName: "",
+            width: 110,
+            headerClass: "header-center tokyoBranchCol",
+            editable: true,
+            cellEditor: "agSelectCellEditor",
+            cellEditorParams: {
+                values: branchOptions
+            } as ISelectCellEditorParams,
+            valueFormatter: (params: ValueFormatterParams) => params.value || "",
+            cellRenderer: (params: ICellRendererParams) => {
+                return (
+                    <div style={{ textAlign: 'left'}}>
+                        {params.value || ''}
+                    </div>
+                );
+            }
+        },
+        {
+            field: "approveStatus",
+            headerName: "",
+            width: 130,
+            cellRenderer: (params: ICellRendererParams) => {
+                const status = params.data?.approveStatus;
+                const content = status === "approved"? (
+                    <span>
+        承認済
+        <a
+            href="#"
+            style={{
+                marginLeft: "5px",
+                color: "#3a8aca"
+            }}
+        >
+          差戻し
+        </a>
+      </span>
+                ) : status === "unapproved"? (
+                    <span>未承認</span>
+                ) : (
+                    <span></span>
+                );
+                return (
+                    <div style={{ textAlign: 'left'}}>
+                        {content}
+                    </div>
+                );
+            },
+            headerClass: "header-center"
+        },
+        {
+            field: "AM",
+            headerClass: "header-center",
+            width: 60,
+        },
+        {
+            headerName: "線便",
+            headerClass: "header-center line-group-header",
+            children: [
+                {
+                    field: "発",
+                    headerClass: "header-center",
+                    width: 85,
+                },
+                {
+                    field: "着",
+                    headerClass: "header-center",
+                    width: 85,
+                },
+                {
+                    field: "系統",
+                    headerClass: "header-center",
+                    width: 65,
+                },
+                {
+                    field: "線便名",
+                    headerClass: "header-center",
+                    width: 120,
+                },
+            ],
+        },
+        { field: "入庫場所", headerClass: "header-center", width: 110 },
+        { field: "入庫時間", headerClass: "header-center", width: 90 },
+        {
+            field: "使用車両(トン)",
+            headerClass: "header-center",
+            width: 125,
+            cellRenderer: (params: ICellRendererParams) => {
+                return (
+                    <div style={{ textAlign: 'right'}}>
+                        {params.value || ''}
+                    </div>
+                );
+            }
+        },
+        ...generateDateColumns()
+    ];
+
+
+    // 处理对话框确认
+    const handleDialogConfirm = (reason: string, changeValue: string) => {
+        if (!selectedCell || selectedCell.rowIndex === null) return;
+
+        const newRowData = [...rowData];
+        const currentValue = selectedCell.currentValue;
+        const newValue = currentValue === "〇"? "" : "〇";
+        const targetRowIndex = selectedCell.rowIndex;
+        const targetColId = selectedCell.colId;
+
+        newRowData[targetRowIndex] = {
+            ...newRowData[targetRowIndex],
+            [targetColId]: newValue
+        };
+        setRowData(newRowData);
+
+        const cellKey = `${targetRowIndex}-${targetColId}`;
+        setModifiedCells(prev => {
+            const newSet = new Set(prev);
+            newSet.add(cellKey);
+            return newSet;
+        });
+
+        setCellReasons(prev => ({
+            ...prev,
+            [cellKey]: reason
+        }));
+
+        setShowDialog(false);
+    };
+
+    // 处理对话框取消
+    const handleDialogCancel = () => {
+        setShowDialog(false);
+    };
+
+    // 处理消息按钮点击 - 切换聊天侧边栏显示状态
+    const handleMessageClick = () => {
+        setShowChat(true);
+    };
+
+    // 处理编辑按钮点击
+    const handleEditClick = () => {
+        alert('編集按钮被点击');
+    };
+
+    const handleAddRow = () => {
+        const newRow: any = {
+            "AM": "",
+            "発": "",
+            "着": "",
+            "系統": "",
+            "線便名": "",
+            "入庫場所": "",
+            "入庫時間": "",
+            "使用車両(トン)": "",
+            "checkboxCol": "",
+            "tokyoBranchCol": "",
+            "approveStatus": ""
+        };
+        for (let i = 1; i <= 31; i++) {
+            newRow[`date_${i}`] = "";
+        }
+
+        setRowData([...rowData, newRow]);
+    };
+
+    // 关闭聊天侧边栏
+    const closeChatSidebar = () => {
+        setShowChat(false);
+    };
+
+    return (
+        <div style={containerStyle}>
+            <div className="order-info-container">
+                <div className="order-info-section">
+                    <div style={{ fontSize: '14px' }}>発注詳細</div>
+                    <button className="message-btn" onClick={handleMessageClick}>
+                        メッセージ
+                    </button>
+                </div>
+
+                <div className="order-info-section">
+                    <h3>輸送パートナー </h3>
+                    <div className="order-info-row">
+                        輸送パートナーID:{orderInfo.deliveryPartner.id}
+                    </div>
+                    <div className="order-info-row">
+                        輸送パートナー名:{orderInfo.deliveryPartner.name}
+                    </div>
+                </div>
+
+                <div className="order-info-section">
+                    <h3>状態</h3>
+                    <table className="status-section">
+                        <thead>
+                        <tr>
+                            <th>会社コード</th>
+                            <th>ステータス</th>
+                            <th>version</th>
+                            <th>指示書送付</th>
+                            <th>承諾</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        <tr>
+                            <td>{orderInfo.status.companyCode}</td>
+                            <td>{orderInfo.status.status}</td>
+                            <td>{orderInfo.status.version}</td>
+                            <td>{orderInfo.status.instructionDate}</td>
+                            <td>{orderInfo.status.approvalDate}</td>
+                        </tr>
+                        </tbody>
+                    </table>
+                </div>
+
+                <div className="order-info-section">
+                    <h3>月間運行指示書</h3>
+                    <div className="version-select-container">
+                        <label>version選択</label>
+                        <select value={orderInfo.monthlyInstruction.selectedVersion}>
+                            {orderInfo.monthlyInstruction.versionOptions.map(version => (
+                                <option key={version} value={version}>{version}</option>
+                            ))}
+                        </select>
+                        <button className="edit-btn" onClick={handleEditClick}>
+                            編集
+                        </button>
+                    </div>
+                </div>
+            </div>
+
+            <div style={gridStyle} className="ag-theme-alpine">
+                <AgGridReact
+                    rowData={rowData}
+                    columnDefs={columnDefs}
+                    domLayout="autoHeight"
+                />
+            </div>
+
+            <button className="add-row-btn" onClick={handleAddRow}>
+                +追加
+            </button>
+
+            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '30px' }}>
+                <div>
+                    <button className="action-btn">変更を保存</button>
+                    <button className="action-btn" style={{ marginLeft: '10px' }}>輸送パートナーに送付する</button>
+                </div>
+                <button className="action-btn">代理承諾</button>
+            </div>
+
+            <div style={{ marginTop: '80px' }}>
+                <span className="history-title-custom">状態・アクション履歴</span>
+                <table className="history-table-custom">
+                    <tbody>
+                    {historyData.map((item, index) => (
+                        <tr key={index}>
+                            <td className="type-td">{item.type}</td>
+                            <td className="date-td">{item.date}</td>
+                            <td className="action-td">{item.action}</td>
+                        </tr>
+                    ))}
+                    </tbody>
+                </table>
+            </div>
+
+            {/* 使用封装的对话框组件 */}
+            <DateChangeDialog
+                show={showDialog}
+                onClose={handleDialogCancel}
+                onConfirm={handleDialogConfirm}
+                reasonOptions={reasonOptions}
+            />
+
+            {/* 聊天侧边栏 */}
+            {showChat && (
+                <>
+                    {/* 半透明背景遮罩 */}
+                    <div className="overlay" onClick={closeChatSidebar}></div>
+
+                    {/* 聊天侧边栏容器 */}
+                    <div className="chat-sidebar">
+                        <Chat onClose={closeChatSidebar} />
+                    </div>
+                </>
+            )}
+        </div>
+    );
+};
+
+export default GridExample;
+