17 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
01a1dd837f refactor: extract shared applyReorder helper in CarManagement
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/c5f8f1a2-8a8b-4951-8442-76ce37d906ae

Co-authored-by: h <57948770+h@users.noreply.github.com>
2026-04-06 07:48:47 +00:00
copilot-swe-agent[bot]
85b26ca04e fix: preserve AM/PM when dragging reservation; add drag & drop car reordering
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/c5f8f1a2-8a8b-4951-8442-76ce37d906ae

Co-authored-by: h <57948770+h@users.noreply.github.com>
2026-04-06 07:47:08 +00:00
h
8542d092fb Merge pull request #6 from h/copilot/update-reservation-options
Add car reordering and AM/PM period fields for reservations
2026-04-06 16:37:36 +09:00
copilot-swe-agent[bot]
cdf4b6452d Add car reordering and AM/PM period for reservations
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/c0a4b7dc-228e-4e7d-a985-61b9a17de159

Co-authored-by: h <57948770+h@users.noreply.github.com>
2026-04-06 07:12:49 +00:00
h
88b5f8deaf Commit 2026-04-06 15:36:51 +09:00
h
678658b40e Merge pull request #5 from h/copilot/update-vehicle-indicator-display
Updating vehicle indicator and editing interface
2026-03-22 13:26:06 +09:00
copilot-swe-agent[bot]
6864026497 Changes before error encountered
Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/a42d4e36-a3cf-4ff7-b1cb-f076e601b1b8
2026-03-22 04:25:00 +00:00
h
6f23f9b6e9 Merge pull request #4 from h/copilot/add-field-and-sync-features
Implementing vehicle details and real-time editing synchronization
2026-03-22 13:00:47 +09:00
copilot-swe-agent[bot]
ece803ee1d feat: add inspection_expiry/has_etc/tire_type fields, icons in schedule view, and WebSocket real-time sync
Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/6d0f25ae-6db4-4937-ae2b-6674456a5ca1
2026-03-22 03:58:07 +00:00
h
ea564b18c5 Merge pull request #3 from h/copilot/add-popup-for-edit-delete-reservations
Add timeline view, right-click context menu on reservations, fix trust proxy
2026-03-21 03:52:02 +09:00
copilot-swe-agent[bot]
e9afcf2b28 Add timeline view, right-click context menu, and fix Express trust proxy
- backend/server.js: Add app.set('trust proxy', 1) to fix express-rate-limit
  ValidationError when app runs behind nginx reverse proxy
- ScheduleView.jsx: Add right-click context menu on reservation blocks with
  Edit and Delete options; closes on click-outside or Escape
- ScheduleView.module.css: Add context menu styles
- TimelineView.jsx: New Gantt-style monthly timeline view showing all
  reservations sorted by date, with month navigation and right-click menu
- TimelineView.module.css: Styles for the timeline view
- App.jsx: Add 'タイムライン' tab to navigation

Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/d03ca12c-21ce-45a0-881f-919d6635e7fb
2026-03-20 18:50:51 +00:00
copilot-swe-agent[bot]
8c03616a7e Initial plan 2026-03-20 18:38:28 +00:00
h
dccb632cd9 Merge pull request #2 from h/copilot/disable-drag-drop-for-touch
Disable touch drag & drop, warn on car delete with reservations, support configurable backend URL
2026-03-21 03:21:50 +09:00
copilot-swe-agent[bot]
8e2e6332d8 Disable touch drag & drop, warn on car delete with reservations, configure backend URL
Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/cd194ca1-b339-4f2f-b717-31a0ba193964
2026-03-20 18:19:53 +00:00
copilot-swe-agent[bot]
921002a3c6 Initial plan 2026-03-20 18:13:46 +00:00
h
21d233965d Merge pull request #1 from h/copilot/create-car-rental-schedule-system
Add car rental schedule management system (React+Vite + Express+SQLite)
2026-03-21 03:07:15 +09:00
copilot-swe-agent[bot]
3d92f4902d Implement car reservation schedule management system
Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/1d8c6b05-0e8d-4484-a2d8-8d427dfad9cb
2026-03-20 18:03:33 +00:00
3 changed files with 59 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { api } from '../api.js'; import { api } from '../api.js';
import { isInspectionExpirySoon } from '../utils/carUtils.js'; import { isInspectionExpirySoon } from '../utils/carUtils.js';
import styles from './CarManagement.module.css'; import styles from './CarManagement.module.css';
@@ -20,6 +20,8 @@ export default function CarManagement({ reloadKey = 0 }) {
const [editEtc, setEditEtc] = useState(false); const [editEtc, setEditEtc] = useState(false);
const [editTire, setEditTire] = useState('ノーマル'); const [editTire, setEditTire] = useState('ノーマル');
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [dragOverIdx, setDragOverIdx] = useState(null);
const dragSrcIdx = useRef(null);
const loadCars = useCallback(async () => { const loadCars = useCallback(async () => {
try { try {
@@ -116,11 +118,7 @@ export default function CarManagement({ reloadKey = 0 }) {
} }
}; };
const handleReorder = async (index, direction) => { const applyReorder = async (newCars) => {
const newCars = [...cars];
const swapIndex = index + direction;
if (swapIndex < 0 || swapIndex >= newCars.length) return;
[newCars[index], newCars[swapIndex]] = [newCars[swapIndex], newCars[index]];
setCars(newCars); setCars(newCars);
try { try {
await api.reorderCars(newCars.map((c) => c.id)); await api.reorderCars(newCars.map((c) => c.id));
@@ -130,6 +128,40 @@ export default function CarManagement({ reloadKey = 0 }) {
} }
}; };
const handleReorder = async (index, direction) => {
const swapIndex = index + direction;
if (swapIndex < 0 || swapIndex >= cars.length) return;
const newCars = [...cars];
[newCars[index], newCars[swapIndex]] = [newCars[swapIndex], newCars[index]];
await applyReorder(newCars);
};
const handleDragStart = (index) => {
dragSrcIdx.current = index;
};
const handleDragOver = (e, index) => {
e.preventDefault();
setDragOverIdx(index);
};
const handleDragEnd = () => {
setDragOverIdx(null);
dragSrcIdx.current = null;
};
const handleDrop = async (e, dropIndex) => {
e.preventDefault();
const srcIndex = dragSrcIdx.current;
setDragOverIdx(null);
dragSrcIdx.current = null;
if (srcIndex === null || srcIndex === dropIndex) return;
const newCars = [...cars];
const [moved] = newCars.splice(srcIndex, 1);
newCars.splice(dropIndex, 0, moved);
await applyReorder(newCars);
};
return ( return (
<div className={styles.container}> <div className={styles.container}>
<h2 className={styles.heading}>代車管理</h2> <h2 className={styles.heading}>代車管理</h2>
@@ -217,7 +249,15 @@ export default function CarManagement({ reloadKey = 0 }) {
</tr> </tr>
)} )}
{cars.map((car, carIdx) => ( {cars.map((car, carIdx) => (
<tr key={car.id}> <tr
key={car.id}
draggable
onDragStart={() => handleDragStart(carIdx)}
onDragOver={(e) => handleDragOver(e, carIdx)}
onDragEnd={handleDragEnd}
onDrop={(e) => handleDrop(e, carIdx)}
className={dragOverIdx === carIdx ? styles.dragOver : ''}
>
<td className={styles.idCell}> <td className={styles.idCell}>
<div className={styles.orderBtns}> <div className={styles.orderBtns}>
<button <button

View File

@@ -111,6 +111,16 @@
background: #fafafa; background: #fafafa;
} }
.table tbody tr[draggable] {
cursor: grab;
}
.dragOver {
background: #eff6ff !important;
outline: 2px dashed #1a56db;
outline-offset: -2px;
}
.idCell { .idCell {
color: #9ca3af; color: #9ca3af;
width: 80px; width: 80px;

View File

@@ -224,6 +224,8 @@ export default function ScheduleView({ reloadKey = 0 }) {
end_date: newEndDate, end_date: newEndDate,
customer_name: reservation.customer_name, customer_name: reservation.customer_name,
notes: reservation.notes, notes: reservation.notes,
start_period: reservation.start_period,
end_period: reservation.end_period,
}); });
await loadData(); await loadData();
} catch (err) { } catch (err) {