feat: SAZLT info row, 16/24h shifts, VN/NN font colors
- Added SAZLT info row (between TKB and Metro) with toggle - Added 16h and 24h shift codes (progressive green shades) - VN people get red font color on A/B shifts - NN people get blue font color on A/B shifts - Changed B (Noční) background to light blue-gray for readability Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -231,10 +231,11 @@ interface ScheduleAppProps {
|
|||||||
function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileNameChange, onClearCompare }: ScheduleAppProps) {
|
function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileNameChange, onClearCompare }: ScheduleAppProps) {
|
||||||
const {
|
const {
|
||||||
people, tunnelClosures, tunnelColors,
|
people, tunnelClosures, tunnelColors,
|
||||||
metroClosures, metroColors, d8Closures, d8Colors,
|
metroClosures, metroColors, d8Closures, d8Colors, sazltClosures, sazltColors,
|
||||||
dayComments, cellComments,
|
dayComments, cellComments,
|
||||||
setCell, setCellColor, moveCell, setTunnelClosure, setTunnelClosureColor,
|
setCell, setCellColor, moveCell, setTunnelClosure, setTunnelClosureColor,
|
||||||
setMetroClosure, setMetroClosureColor, setD8Closure, setD8ClosureColor,
|
setMetroClosure, setMetroClosureColor, setD8Closure, setD8ClosureColor,
|
||||||
|
setSazltClosure, setSazltClosureColor,
|
||||||
undo, canUndo,
|
undo, canUndo,
|
||||||
addDayComment, removeDayComment,
|
addDayComment, removeDayComment,
|
||||||
addCellComment, removeCellComment,
|
addCellComment, removeCellComment,
|
||||||
@@ -407,6 +408,7 @@ function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileName
|
|||||||
const [showProposals, setShowProposals] = useState(false)
|
const [showProposals, setShowProposals] = useState(false)
|
||||||
const [showMetro, setShowMetro] = useState(true)
|
const [showMetro, setShowMetro] = useState(true)
|
||||||
const [showD8, setShowD8] = useState(true)
|
const [showD8, setShowD8] = useState(true)
|
||||||
|
const [showSazlt, setShowSazlt] = useState(true)
|
||||||
const [hiddenValues, setHiddenValues] = useState<Set<string>>(new Set())
|
const [hiddenValues, setHiddenValues] = useState<Set<string>>(new Set())
|
||||||
|
|
||||||
const handleExportPdf = useCallback(async (month: number) => {
|
const handleExportPdf = useCallback(async (month: number) => {
|
||||||
@@ -428,17 +430,20 @@ function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileName
|
|||||||
const contextInfoRowClosure = contextMenu
|
const contextInfoRowClosure = contextMenu
|
||||||
? contextInfoRowId === 'metro' ? metroClosures.get(contextMenu.dayIdx)
|
? contextInfoRowId === 'metro' ? metroClosures.get(contextMenu.dayIdx)
|
||||||
: contextInfoRowId === 'd8' ? d8Closures.get(contextMenu.dayIdx)
|
: contextInfoRowId === 'd8' ? d8Closures.get(contextMenu.dayIdx)
|
||||||
|
: contextInfoRowId === 'sazlt' ? sazltClosures.get(contextMenu.dayIdx)
|
||||||
: undefined
|
: undefined
|
||||||
: undefined
|
: undefined
|
||||||
const contextInfoRowColor = contextMenu
|
const contextInfoRowColor = contextMenu
|
||||||
? contextInfoRowId === 'metro' ? metroColors.get(contextMenu.dayIdx)
|
? contextInfoRowId === 'metro' ? metroColors.get(contextMenu.dayIdx)
|
||||||
: contextInfoRowId === 'd8' ? d8Colors.get(contextMenu.dayIdx)
|
: contextInfoRowId === 'd8' ? d8Colors.get(contextMenu.dayIdx)
|
||||||
|
: contextInfoRowId === 'sazlt' ? sazltColors.get(contextMenu.dayIdx)
|
||||||
: undefined
|
: undefined
|
||||||
: undefined
|
: undefined
|
||||||
const handleInfoRowSetColor = useCallback((dayIdx: number, color: string | null) => {
|
const handleInfoRowSetColor = useCallback((dayIdx: number, color: string | null) => {
|
||||||
if (contextInfoRowId === 'metro') setMetroClosureColor(dayIdx, color)
|
if (contextInfoRowId === 'metro') setMetroClosureColor(dayIdx, color)
|
||||||
else if (contextInfoRowId === 'd8') setD8ClosureColor(dayIdx, color)
|
else if (contextInfoRowId === 'd8') setD8ClosureColor(dayIdx, color)
|
||||||
}, [contextInfoRowId, setMetroClosureColor, setD8ClosureColor])
|
else if (contextInfoRowId === 'sazlt') setSazltClosureColor(dayIdx, color)
|
||||||
|
}, [contextInfoRowId, setMetroClosureColor, setD8ClosureColor, setSazltClosureColor])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-slate-900">
|
<div className="min-h-screen bg-slate-900">
|
||||||
@@ -477,6 +482,8 @@ function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileName
|
|||||||
showD8={showD8}
|
showD8={showD8}
|
||||||
onToggleMetro={() => setShowMetro(v => !v)}
|
onToggleMetro={() => setShowMetro(v => !v)}
|
||||||
onToggleD8={() => setShowD8(v => !v)}
|
onToggleD8={() => setShowD8(v => !v)}
|
||||||
|
showSazlt={showSazlt}
|
||||||
|
onToggleSazlt={() => setShowSazlt(v => !v)}
|
||||||
hiddenValues={hiddenValues}
|
hiddenValues={hiddenValues}
|
||||||
onToggleValue={(code: string) => setHiddenValues(prev => {
|
onToggleValue={(code: string) => setHiddenValues(prev => {
|
||||||
const next = new Set(prev)
|
const next = new Set(prev)
|
||||||
@@ -497,6 +504,8 @@ function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileName
|
|||||||
metroColors={metroColors}
|
metroColors={metroColors}
|
||||||
d8Closures={d8Closures}
|
d8Closures={d8Closures}
|
||||||
d8Colors={d8Colors}
|
d8Colors={d8Colors}
|
||||||
|
sazltClosures={sazltClosures}
|
||||||
|
sazltColors={sazltColors}
|
||||||
dayComments={dayComments}
|
dayComments={dayComments}
|
||||||
cellComments={cellComments}
|
cellComments={cellComments}
|
||||||
dragState={dragState}
|
dragState={dragState}
|
||||||
@@ -505,8 +514,10 @@ function ScheduleApp({ fileId, fileName, data, compareFileId, onBack, onFileName
|
|||||||
onSetTunnelClosure={setTunnelClosure}
|
onSetTunnelClosure={setTunnelClosure}
|
||||||
onSetMetroClosure={setMetroClosure}
|
onSetMetroClosure={setMetroClosure}
|
||||||
onSetD8Closure={setD8Closure}
|
onSetD8Closure={setD8Closure}
|
||||||
|
onSetSazltClosure={setSazltClosure}
|
||||||
showMetro={showMetro}
|
showMetro={showMetro}
|
||||||
showD8={showD8}
|
showD8={showD8}
|
||||||
|
showSazlt={showSazlt}
|
||||||
hiddenValues={hiddenValues}
|
hiddenValues={hiddenValues}
|
||||||
scrollRef={scrollRef}
|
scrollRef={scrollRef}
|
||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo, useState, useCallback, useRef, memo, useEffect } from 'react'
|
import { useMemo, useState, useCallback, useRef, memo, useEffect } from 'react'
|
||||||
import type { DayInfo, Person, DragState, ScheduleData } from './types'
|
import type { DayInfo, Person, DragState, ScheduleData } from './types'
|
||||||
import { getCellStyle, getContrastColor } from './cellColors'
|
import { getCellStyle, getCellStyleForPerson, getContrastColor } from './cellColors'
|
||||||
import { getHolidayMap } from './holidays'
|
import { getHolidayMap } from './holidays'
|
||||||
|
|
||||||
const CELL_W = 32
|
const CELL_W = 32
|
||||||
@@ -27,6 +27,8 @@ interface ScheduleTableProps {
|
|||||||
metroColors: Map<number, string>
|
metroColors: Map<number, string>
|
||||||
d8Closures: Map<number, string>
|
d8Closures: Map<number, string>
|
||||||
d8Colors: Map<number, string>
|
d8Colors: Map<number, string>
|
||||||
|
sazltClosures: Map<number, string>
|
||||||
|
sazltColors: Map<number, string>
|
||||||
dayComments: Map<number, string>
|
dayComments: Map<number, string>
|
||||||
cellComments: Map<string, string>
|
cellComments: Map<string, string>
|
||||||
dragState: DragState | null
|
dragState: DragState | null
|
||||||
@@ -35,9 +37,11 @@ interface ScheduleTableProps {
|
|||||||
onSetTunnelClosure: (dayIdx: number, text: string | null) => void
|
onSetTunnelClosure: (dayIdx: number, text: string | null) => void
|
||||||
onSetMetroClosure: (dayIdx: number, text: string | null) => void
|
onSetMetroClosure: (dayIdx: number, text: string | null) => void
|
||||||
onSetD8Closure: (dayIdx: number, text: string | null) => void
|
onSetD8Closure: (dayIdx: number, text: string | null) => void
|
||||||
|
onSetSazltClosure: (dayIdx: number, text: string | null) => void
|
||||||
scrollRef: React.RefObject<HTMLDivElement | null>
|
scrollRef: React.RefObject<HTMLDivElement | null>
|
||||||
showMetro: boolean
|
showMetro: boolean
|
||||||
showD8: boolean
|
showD8: boolean
|
||||||
|
showSazlt: boolean
|
||||||
hiddenValues: Set<string>
|
hiddenValues: Set<string>
|
||||||
onContextMenu: (dayIdx: number, personId: string | null, x: number, y: number, selectedCells: SelectedCell[]) => void
|
onContextMenu: (dayIdx: number, personId: string | null, x: number, y: number, selectedCells: SelectedCell[]) => void
|
||||||
onTunnelContextMenu: (dayIdx: number, x: number, y: number) => void
|
onTunnelContextMenu: (dayIdx: number, x: number, y: number) => void
|
||||||
@@ -46,7 +50,7 @@ interface ScheduleTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface EditingCell {
|
interface EditingCell {
|
||||||
personId: string | '__tunnel__' | '__metro__' | '__d8__'
|
personId: string | '__tunnel__' | '__metro__' | '__d8__' | '__sazlt__'
|
||||||
dayIdx: number
|
dayIdx: number
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
@@ -101,7 +105,7 @@ const PersonRow = memo(function PersonRow({
|
|||||||
const value = cellData?.v ?? ''
|
const value = cellData?.v ?? ''
|
||||||
const isColorOnly = !value && !!cellData?.color
|
const isColorOnly = !value && !!cellData?.color
|
||||||
const isValueHidden = !!(value && hiddenValues.has(value)) || (isColorOnly && hiddenValues.has('__color_only__'))
|
const isValueHidden = !!(value && hiddenValues.has(value)) || (isColorOnly && hiddenValues.has('__color_only__'))
|
||||||
const style = getCellStyle(value || undefined)
|
const style = getCellStyleForPerson(value || undefined, person.note)
|
||||||
const isHoliday = holidays.has(`${d.year}-${d.month}-${d.day}`)
|
const isHoliday = holidays.has(`${d.year}-${d.month}-${d.day}`)
|
||||||
const isWeekend = d.weekend || isHoliday
|
const isWeekend = d.weekend || isHoliday
|
||||||
const commentKey = `${person.id}-${d.idx}`
|
const commentKey = `${person.id}-${d.idx}`
|
||||||
@@ -232,11 +236,11 @@ const PersonRow = memo(function PersonRow({
|
|||||||
export function ScheduleTable(props: ScheduleTableProps) {
|
export function ScheduleTable(props: ScheduleTableProps) {
|
||||||
const {
|
const {
|
||||||
dayIndex, people, tunnelClosures, tunnelColors,
|
dayIndex, people, tunnelClosures, tunnelColors,
|
||||||
metroClosures, metroColors, d8Closures, d8Colors,
|
metroClosures, metroColors, d8Closures, d8Colors, sazltClosures, sazltColors,
|
||||||
dayComments, cellComments,
|
dayComments, cellComments,
|
||||||
dragState, onCellPointerDown, onSetCell, onSetTunnelClosure,
|
dragState, onCellPointerDown, onSetCell, onSetTunnelClosure,
|
||||||
onSetMetroClosure, onSetD8Closure,
|
onSetMetroClosure, onSetD8Closure, onSetSazltClosure,
|
||||||
showMetro, showD8, hiddenValues,
|
showMetro, showD8, showSazlt, hiddenValues,
|
||||||
scrollRef, onContextMenu, onTunnelContextMenu, onInfoRowContextMenu, compareData,
|
scrollRef, onContextMenu, onTunnelContextMenu, onInfoRowContextMenu, compareData,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
@@ -324,6 +328,10 @@ export function ScheduleTable(props: ScheduleTableProps) {
|
|||||||
setEditingCell({ personId: '__d8__', dayIdx, value: currentValue })
|
setEditingCell({ personId: '__d8__', dayIdx, value: currentValue })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const onStartEditSazlt = useCallback((dayIdx: number, currentValue: string) => {
|
||||||
|
setEditingCell({ personId: '__sazlt__', dayIdx, value: currentValue })
|
||||||
|
}, [])
|
||||||
|
|
||||||
const onEditChange = useCallback((value: string) => {
|
const onEditChange = useCallback((value: string) => {
|
||||||
setEditingCell(prev => prev ? { ...prev, value } : null)
|
setEditingCell(prev => prev ? { ...prev, value } : null)
|
||||||
}, [])
|
}, [])
|
||||||
@@ -337,11 +345,13 @@ export function ScheduleTable(props: ScheduleTableProps) {
|
|||||||
onSetMetroClosure(editingCell.dayIdx, trimmed || null)
|
onSetMetroClosure(editingCell.dayIdx, trimmed || null)
|
||||||
} else if (editingCell.personId === '__d8__') {
|
} else if (editingCell.personId === '__d8__') {
|
||||||
onSetD8Closure(editingCell.dayIdx, trimmed || null)
|
onSetD8Closure(editingCell.dayIdx, trimmed || null)
|
||||||
|
} else if (editingCell.personId === '__sazlt__') {
|
||||||
|
onSetSazltClosure(editingCell.dayIdx, trimmed || null)
|
||||||
} else {
|
} else {
|
||||||
onSetCell(editingCell.personId, editingCell.dayIdx, trimmed || null)
|
onSetCell(editingCell.personId, editingCell.dayIdx, trimmed || null)
|
||||||
}
|
}
|
||||||
setEditingCell(null)
|
setEditingCell(null)
|
||||||
}, [editingCell, onSetCell, onSetTunnelClosure, onSetMetroClosure, onSetD8Closure])
|
}, [editingCell, onSetCell, onSetTunnelClosure, onSetMetroClosure, onSetD8Closure, onSetSazltClosure])
|
||||||
|
|
||||||
const onEditCancel = useCallback(() => {
|
const onEditCancel = useCallback(() => {
|
||||||
setEditingCell(null)
|
setEditingCell(null)
|
||||||
@@ -601,7 +611,7 @@ export function ScheduleTable(props: ScheduleTableProps) {
|
|||||||
|
|
||||||
// Helper: render info row cells (right column)
|
// Helper: render info row cells (right column)
|
||||||
const renderInfoRowCells = (
|
const renderInfoRowCells = (
|
||||||
rowId: '__tunnel__' | '__metro__' | '__d8__',
|
rowId: '__tunnel__' | '__metro__' | '__d8__' | '__sazlt__',
|
||||||
closures: Map<number, string>,
|
closures: Map<number, string>,
|
||||||
colors: Map<number, string>,
|
colors: Map<number, string>,
|
||||||
defaultBgClass: string,
|
defaultBgClass: string,
|
||||||
@@ -698,7 +708,10 @@ export function ScheduleTable(props: ScheduleTableProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TKB info row label */}
|
{/* TKB info row label */}
|
||||||
{renderInfoRowLabel('TKB', 'border-slate-600')}
|
{renderInfoRowLabel('TKB', 'border-slate-700')}
|
||||||
|
|
||||||
|
{/* SAZLT info row label */}
|
||||||
|
{showSazlt && renderInfoRowLabel('SAZLT', 'border-slate-700')}
|
||||||
|
|
||||||
{/* Metro info row label */}
|
{/* Metro info row label */}
|
||||||
{showMetro && renderInfoRowLabel('Metro', 'border-slate-700')}
|
{showMetro && renderInfoRowLabel('Metro', 'border-slate-700')}
|
||||||
@@ -811,9 +824,14 @@ export function ScheduleTable(props: ScheduleTableProps) {
|
|||||||
|
|
||||||
{/* TKB info row */}
|
{/* TKB info row */}
|
||||||
{renderInfoRowCells('__tunnel__', tunnelClosures, tunnelColors,
|
{renderInfoRowCells('__tunnel__', tunnelClosures, tunnelColors,
|
||||||
'bg-orange-700/40 text-orange-200', 'border-slate-600', 'border-orange-400', 'TKB',
|
'bg-orange-700/40 text-orange-200', 'border-slate-700', 'border-orange-400', 'TKB',
|
||||||
onTunnelContextMenu, onStartEditTunnel)}
|
onTunnelContextMenu, onStartEditTunnel)}
|
||||||
|
|
||||||
|
{/* SAZLT info row */}
|
||||||
|
{showSazlt && renderInfoRowCells('__sazlt__', sazltClosures, sazltColors,
|
||||||
|
'bg-amber-700/40 text-amber-200', 'border-slate-700', 'border-amber-400', 'SAZLT',
|
||||||
|
(dayIdx, x, y) => onInfoRowContextMenu(dayIdx, 'sazlt', x, y), onStartEditSazlt)}
|
||||||
|
|
||||||
{/* Metro info row */}
|
{/* Metro info row */}
|
||||||
{showMetro && renderInfoRowCells('__metro__', metroClosures, metroColors,
|
{showMetro && renderInfoRowCells('__metro__', metroClosures, metroColors,
|
||||||
'bg-blue-700/40 text-blue-200', 'border-slate-700', 'border-blue-400', 'Metro',
|
'bg-blue-700/40 text-blue-200', 'border-slate-700', 'border-blue-400', 'Metro',
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ interface ToolbarProps {
|
|||||||
activeMonth?: number
|
activeMonth?: number
|
||||||
showMetro: boolean
|
showMetro: boolean
|
||||||
showD8: boolean
|
showD8: boolean
|
||||||
|
showSazlt: boolean
|
||||||
onToggleMetro: () => void
|
onToggleMetro: () => void
|
||||||
onToggleD8: () => void
|
onToggleD8: () => void
|
||||||
|
onToggleSazlt: () => void
|
||||||
hiddenValues: Set<string>
|
hiddenValues: Set<string>
|
||||||
onToggleValue: (code: string) => void
|
onToggleValue: (code: string) => void
|
||||||
diffFileName?: string | null
|
diffFileName?: string | null
|
||||||
@@ -45,8 +47,10 @@ export function Toolbar({
|
|||||||
activeMonth,
|
activeMonth,
|
||||||
showMetro,
|
showMetro,
|
||||||
showD8,
|
showD8,
|
||||||
|
showSazlt,
|
||||||
onToggleMetro,
|
onToggleMetro,
|
||||||
onToggleD8,
|
onToggleD8,
|
||||||
|
onToggleSazlt,
|
||||||
hiddenValues,
|
hiddenValues,
|
||||||
onToggleValue,
|
onToggleValue,
|
||||||
diffFileName,
|
diffFileName,
|
||||||
@@ -177,6 +181,16 @@ export function Toolbar({
|
|||||||
>
|
>
|
||||||
D8
|
D8
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onToggleSazlt}
|
||||||
|
className={`px-2 py-1 rounded text-[10px] border cursor-pointer transition-colors
|
||||||
|
${showSazlt
|
||||||
|
? 'bg-orange-800/60 text-orange-200 border-orange-600'
|
||||||
|
: 'bg-slate-800 text-slate-500 border-slate-700 opacity-50'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
SAZLT
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="h-5 w-px bg-slate-700" />
|
<div className="h-5 w-px bg-slate-700" />
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ const CELL_STYLES: Record<string, CellStyle> = {
|
|||||||
'6': { bg: '#E8F5E9', text: '#333', label: '6h směna' },
|
'6': { bg: '#E8F5E9', text: '#333', label: '6h směna' },
|
||||||
'8': { bg: '#CCFFCC', text: '#333', label: '8h směna' },
|
'8': { bg: '#CCFFCC', text: '#333', label: '8h směna' },
|
||||||
'12': { bg: '#A3D977', text: '#333', label: '12h směna' },
|
'12': { bg: '#A3D977', text: '#333', label: '12h směna' },
|
||||||
|
'16': { bg: '#66BB6A', text: '#fff', label: '16h směna' },
|
||||||
|
'24': { bg: '#2E7D32', text: '#fff', label: '24h směna' },
|
||||||
'A': { bg: '#FFE082', text: '#333', label: 'Ranní (denní směna)' },
|
'A': { bg: '#FFE082', text: '#333', label: 'Ranní (denní směna)' },
|
||||||
'B': { bg: '#5C6BC0', text: '#fff', label: 'Noční směna' },
|
'B': { bg: '#B0BEC5', text: '#333', label: 'Noční směna' },
|
||||||
'D': { bg: '#FFFF00', text: '#333', label: 'Dovolená' },
|
'D': { bg: '#FFFF00', text: '#333', label: 'Dovolená' },
|
||||||
'D/2': { bg: '#FFF9C4', text: '#333', label: 'Půl den dovolená' },
|
'D/2': { bg: '#FFF9C4', text: '#333', label: 'Půl den dovolená' },
|
||||||
'N': { bg: '#FF4444', text: '#fff', label: 'Nemocenská' },
|
'N': { bg: '#FF4444', text: '#fff', label: 'Nemocenská' },
|
||||||
@@ -25,6 +27,19 @@ export function getCellStyle(value: string | undefined): CellStyle | null {
|
|||||||
return CELL_STYLES[v] ?? null
|
return CELL_STYLES[v] ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Person-aware style: VN/NN people get distinct font colors for A/B shifts
|
||||||
|
export function getCellStyleForPerson(value: string | undefined, personNote?: string): CellStyle | null {
|
||||||
|
if (!value) return null
|
||||||
|
const v = value.trim()
|
||||||
|
const base = CELL_STYLES[v]
|
||||||
|
if (!base) return null
|
||||||
|
if (v === 'A' || v === 'B') {
|
||||||
|
if (personNote === 'VN') return { ...base, text: '#D32F2F' } // red font
|
||||||
|
if (personNote === 'NN') return { ...base, text: '#1565C0' } // blue font
|
||||||
|
}
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
export function getAllCellStyles(): Record<string, CellStyle> {
|
export function getAllCellStyles(): Record<string, CellStyle> {
|
||||||
return { ...CELL_STYLES }
|
return { ...CELL_STYLES }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ interface ScheduleSnapshot {
|
|||||||
metroColors: Map<number, string>
|
metroColors: Map<number, string>
|
||||||
d8Closures: Map<number, string>
|
d8Closures: Map<number, string>
|
||||||
d8Colors: Map<number, string>
|
d8Colors: Map<number, string>
|
||||||
|
sazltClosures: Map<number, string>
|
||||||
|
sazltColors: Map<number, string>
|
||||||
dayComments: Map<number, string>
|
dayComments: Map<number, string>
|
||||||
cellComments: Map<string, string>
|
cellComments: Map<string, string>
|
||||||
}
|
}
|
||||||
@@ -77,6 +79,24 @@ export function useScheduleState(
|
|||||||
return m
|
return m
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [sazltClosures, setSazltClosuresState] = useState<Map<number, string>>(() => {
|
||||||
|
const m = new Map<number, string>()
|
||||||
|
if (initialInfoRows?.sazlt) {
|
||||||
|
for (const entry of initialInfoRows.sazlt) m.set(entry.dayIdx, entry.text)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
})
|
||||||
|
|
||||||
|
const [sazltColors, setSazltColorsState] = useState<Map<number, string>>(() => {
|
||||||
|
const m = new Map<number, string>()
|
||||||
|
if (initialInfoRows?.sazlt) {
|
||||||
|
for (const entry of initialInfoRows.sazlt) {
|
||||||
|
if (entry.color) m.set(entry.dayIdx, entry.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
})
|
||||||
|
|
||||||
const [dayComments, setDayCommentsState] = useState<Map<number, string>>(() => {
|
const [dayComments, setDayCommentsState] = useState<Map<number, string>>(() => {
|
||||||
const m = new Map<number, string>()
|
const m = new Map<number, string>()
|
||||||
if (initialDayComments) {
|
if (initialDayComments) {
|
||||||
@@ -104,11 +124,13 @@ export function useScheduleState(
|
|||||||
metroColors: new Map(metroColors),
|
metroColors: new Map(metroColors),
|
||||||
d8Closures: new Map(d8Closures),
|
d8Closures: new Map(d8Closures),
|
||||||
d8Colors: new Map(d8Colors),
|
d8Colors: new Map(d8Colors),
|
||||||
|
sazltClosures: new Map(sazltClosures),
|
||||||
|
sazltColors: new Map(sazltColors),
|
||||||
dayComments: new Map(dayComments),
|
dayComments: new Map(dayComments),
|
||||||
cellComments: new Map(cellComments),
|
cellComments: new Map(cellComments),
|
||||||
})
|
})
|
||||||
if (historyRef.current.length > 50) historyRef.current.shift()
|
if (historyRef.current.length > 50) historyRef.current.shift()
|
||||||
}, [people, tunnelClosures, tunnelColors, metroClosures, metroColors, d8Closures, d8Colors, dayComments, cellComments])
|
}, [people, tunnelClosures, tunnelColors, metroClosures, metroColors, d8Closures, d8Colors, sazltClosures, sazltColors, dayComments, cellComments])
|
||||||
|
|
||||||
const setCell = useCallback((personId: string, dayIdx: number, value: string | null) => {
|
const setCell = useCallback((personId: string, dayIdx: number, value: string | null) => {
|
||||||
pushHistory()
|
pushHistory()
|
||||||
@@ -200,6 +222,26 @@ export function useScheduleState(
|
|||||||
})
|
})
|
||||||
}, [pushHistory])
|
}, [pushHistory])
|
||||||
|
|
||||||
|
const setSazltClosure = useCallback((dayIdx: number, text: string | null) => {
|
||||||
|
pushHistory()
|
||||||
|
setSazltClosuresState(prev => {
|
||||||
|
const next = new Map(prev)
|
||||||
|
if (text) next.set(dayIdx, text)
|
||||||
|
else next.delete(dayIdx)
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}, [pushHistory])
|
||||||
|
|
||||||
|
const setSazltClosureColor = useCallback((dayIdx: number, color: string | null) => {
|
||||||
|
pushHistory()
|
||||||
|
setSazltColorsState(prev => {
|
||||||
|
const next = new Map(prev)
|
||||||
|
if (color) next.set(dayIdx, color)
|
||||||
|
else next.delete(dayIdx)
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}, [pushHistory])
|
||||||
|
|
||||||
const moveCell = useCallback((personId: string, fromIdx: number, toIdx: number) => {
|
const moveCell = useCallback((personId: string, fromIdx: number, toIdx: number) => {
|
||||||
if (fromIdx === toIdx) return
|
if (fromIdx === toIdx) return
|
||||||
pushHistory()
|
pushHistory()
|
||||||
@@ -263,6 +305,8 @@ export function useScheduleState(
|
|||||||
setMetroColorsState(snapshot.metroColors)
|
setMetroColorsState(snapshot.metroColors)
|
||||||
setD8ClosuresState(snapshot.d8Closures)
|
setD8ClosuresState(snapshot.d8Closures)
|
||||||
setD8ColorsState(snapshot.d8Colors)
|
setD8ColorsState(snapshot.d8Colors)
|
||||||
|
setSazltClosuresState(snapshot.sazltClosures)
|
||||||
|
setSazltColorsState(snapshot.sazltColors)
|
||||||
setDayCommentsState(snapshot.dayComments)
|
setDayCommentsState(snapshot.dayComments)
|
||||||
setCellCommentsState(snapshot.cellComments)
|
setCellCommentsState(snapshot.cellComments)
|
||||||
}, [])
|
}, [])
|
||||||
@@ -285,6 +329,10 @@ export function useScheduleState(
|
|||||||
dayIdx, text,
|
dayIdx, text,
|
||||||
...(d8Colors.get(dayIdx) ? { color: d8Colors.get(dayIdx) } : {}),
|
...(d8Colors.get(dayIdx) ? { color: d8Colors.get(dayIdx) } : {}),
|
||||||
})),
|
})),
|
||||||
|
sazlt: Array.from(sazltClosures.entries()).map(([dayIdx, text]) => ({
|
||||||
|
dayIdx, text,
|
||||||
|
...(sazltColors.get(dayIdx) ? { color: sazltColors.get(dayIdx) } : {}),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
dayComments: Array.from(dayComments.entries()).map(([dayIdx, text]) => ({ dayIdx, text })),
|
dayComments: Array.from(dayComments.entries()).map(([dayIdx, text]) => ({ dayIdx, text })),
|
||||||
cellComments: Array.from(cellComments.entries()).map(([key, text]) => {
|
cellComments: Array.from(cellComments.entries()).map(([key, text]) => {
|
||||||
@@ -293,7 +341,7 @@ export function useScheduleState(
|
|||||||
const dayIdx = parseInt(key.substring(dashIdx + 1))
|
const dayIdx = parseInt(key.substring(dashIdx + 1))
|
||||||
return { personId, dayIdx, text }
|
return { personId, dayIdx, text }
|
||||||
}),
|
}),
|
||||||
}), [dayIndex, people, tunnelClosures, tunnelColors, metroClosures, metroColors, d8Closures, d8Colors, dayComments, cellComments])
|
}), [dayIndex, people, tunnelClosures, tunnelColors, metroClosures, metroColors, d8Closures, d8Colors, sazltClosures, sazltColors, dayComments, cellComments])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
people,
|
people,
|
||||||
@@ -303,6 +351,8 @@ export function useScheduleState(
|
|||||||
metroColors,
|
metroColors,
|
||||||
d8Closures,
|
d8Closures,
|
||||||
d8Colors,
|
d8Colors,
|
||||||
|
sazltClosures,
|
||||||
|
sazltColors,
|
||||||
dayComments,
|
dayComments,
|
||||||
cellComments,
|
cellComments,
|
||||||
setCell,
|
setCell,
|
||||||
@@ -314,6 +364,8 @@ export function useScheduleState(
|
|||||||
setMetroClosureColor,
|
setMetroClosureColor,
|
||||||
setD8Closure,
|
setD8Closure,
|
||||||
setD8ClosureColor,
|
setD8ClosureColor,
|
||||||
|
setSazltClosure,
|
||||||
|
setSazltClosureColor,
|
||||||
addDayComment,
|
addDayComment,
|
||||||
removeDayComment,
|
removeDayComment,
|
||||||
addCellComment,
|
addCellComment,
|
||||||
|
|||||||
Reference in New Issue
Block a user