Implement cell merging and enhanced weekend formatting

- Add horizontal cell merging for header rows (2-5) using jspreadsheet setMerge
- Day names, year, month, and day values now span across both day/night columns
- Extended weekend highlighting to year/month/day rows under weekend days
- Improved visual hierarchy with grouped date information per day
- Fixed font sizes for better readability (12px for all rotated values)
- Increased day names row height to 50px for better text fit
- Removed bold formatting from "den"/"noc" shift labels

Technical improvements:
- Correct jspreadsheet v4 setMerge syntax: setMerge(cellAddress, colspan, rowspan)
- Excel-style column naming supports AA, AB, AC... format
- Preserved all text rotation and color formatting during merging

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Docker Config Backup
2025-07-28 20:52:31 +02:00
parent 3216f74229
commit eaad398127
2 changed files with 42 additions and 7 deletions

View File

@@ -68,7 +68,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
const dayName = ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"][currentDate.getDay()]
titleRow.push("", "")
dayNameRow.push(dayName, "")
dayNameRow.push(dayName, "") // Day name in first column, empty in second (for merging)
yearRow.push(currentDate.getFullYear().toString(), "")
monthRow.push((currentDate.getMonth() + 1).toString(), "")
dateRow.push(currentDate.getDate().toString(), "")
@@ -232,24 +232,38 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
// Generate styles for day/night shifts based on the Excel pattern
const styles: Record<string, string> = {}
if (selectedMonth && selectedYear) {
// Make day names row (row 2) taller
for (let col = 0; col < (data[0]?.length || 0); col++) {
const colLetter = getExcelColumnName(col)
styles[`${colLetter}2`] = "height: 50px;"
}
// Style header rows
for (let col = 1; col < (data[0]?.length || 0); col++) {
const colLetter = getExcelColumnName(col)
if (col % 2 === 1) { // Day shifts (odd columns after first)
styles[`${colLetter}6`] = "background-color: #ffff00; font-weight: bold;" // Yellow for day
styles[`${colLetter}6`] = "background-color: #ffff00; font-weight: normal;" // Yellow for day, not bold
} else { // Night shifts (even columns after first)
styles[`${colLetter}6`] = "background-color: #00b0f0; font-weight: bold;" // Blue for night
styles[`${colLetter}6`] = "background-color: #00b0f0; font-weight: normal;" // Blue for night, not bold
}
}
// Style weekend days (Saturday/Sunday in day name row)
// Style weekend days (Saturday/Sunday in day name row and date rows below)
for (let col = 1; col < (data[0]?.length || 0); col += 2) {
const dayName = data[1]?.[col]
if (dayName === "Sobota" || dayName === "Neděle") {
const colLetter = getExcelColumnName(col)
const nextColLetter = getExcelColumnName(col + 1)
styles[`${colLetter}2`] = "background-color: #ffd966;" // Weekend day name
styles[`${nextColLetter}2`] = "background-color: #ffd966;"
// Weekend day name row (row 2) - merged cells
styles[`${colLetter}2`] = "background-color: #ffd966; height: 50px;" // Weekend day name with height
styles[`${nextColLetter}2`] = "background-color: #ffd966; height: 50px;"
// Weekend date columns (rows 3, 4, 5 - year, month, day)
for (let row = 3; row <= 5; row++) {
styles[`${colLetter}${row}`] = "background-color: #ffd966;" // Weekend date values
styles[`${nextColLetter}${row}`] = "background-color: #ffd966;" // Weekend date values
}
}
}
}
@@ -278,6 +292,26 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
console.log("jspreadsheet initialized:", !!jspreadsheetInstance.current)
// Apply cell merges for header rows after initialization
if (jspreadsheetInstance.current && selectedMonth && selectedYear) {
const instance = jspreadsheetInstance.current as any
if (instance.setMerge) {
// Merge all pairs in rows 2, 3, 4, 5 (day names, year, month, day)
for (let row = 2; row <= 5; row++) {
for (let col = 1; col < (data[0]?.length || 0); col += 2) {
const colLetter = getExcelColumnName(col)
try {
// Correct syntax: setMerge(cellAddress, colspan, rowspan)
instance.setMerge(`${colLetter}${row}`, 2, 1) // 2 columns, 1 row
console.log(`Merged ${colLetter}${row} with 2 columns`)
} catch (error) {
console.error(`Failed to merge ${colLetter}${row}:`, error)
}
}
}
}
}
// Apply counter-clockwise rotation to data values only (exclude second column which contains field labels)
setTimeout(() => {
const table = spreadsheetRef.current?.querySelector('.jexcel tbody')
@@ -292,7 +326,8 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
// Skip first two columns (row numbers and field labels)
if (cellIndex > 1) {
const originalText = cell.textContent
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 9px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap;">${originalText}</div>`
// Use 12px font for all rotated values (date values, day names, and shifts)
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 20px; display: flex; align-items: center; justify-content: center; white-space: nowrap;">${originalText}</div>`
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB