Add Práce mimo směnu column with proper layout
- Add separator column and Práce mimo směnu column to timeshift spreadsheet - Implement vertical merging for Práce mimo směnu across rows 2-6 - Add proper styling with borders and rotated text - Exclude separator/práce columns from regular merging logic - Add test component for debugging 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
31
components/test-component.tsx
Normal file
31
components/test-component.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
interface TestComponentProps {
|
||||
teamId: string
|
||||
teamName: string
|
||||
}
|
||||
|
||||
export function TestComponent({ teamId, teamName }: TestComponentProps) {
|
||||
return (
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<CardTitle className="flex items-center gap-2">{teamName} - Test Component</CardTitle>
|
||||
<CardDescription>Testing if React components load properly (Team ID: {teamId})</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="border rounded-lg p-4">
|
||||
<p>This is a test component to verify React is working.</p>
|
||||
<p>If you can see this, the basic React setup is functional.</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ interface TimeshiftSpreadsheetProps {
|
||||
teamName: string
|
||||
}
|
||||
|
||||
export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpreadsheetProps) {
|
||||
export function TimeshiftSpreadsheet({ teamId, teamName }: TimeshiftSpreadsheetProps) {
|
||||
const spreadsheetRef = React.useRef<HTMLDivElement>(null)
|
||||
const jspreadsheetInstance = React.useRef<unknown>(null)
|
||||
const currentDate = new Date()
|
||||
@@ -55,7 +55,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
const yearRow = ["rok"]
|
||||
const monthRow = ["měsíc"]
|
||||
const dateRow = ["den"]
|
||||
const shiftRow = [`Pohotovost ${_teamId.toUpperCase()}`]
|
||||
const shiftRow = [`Pohotovost ${teamId.toUpperCase()}`]
|
||||
|
||||
// Generate columns for each day from prevMonthStart to nextMonthEnd
|
||||
const currentDate = new Date(prevMonthStart)
|
||||
@@ -102,6 +102,14 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
"Pohotovost IT"
|
||||
]
|
||||
|
||||
// Add separator column and "Práce mimo směnu" column
|
||||
titleRow.push("", "") // Empty separator + empty for merged cell
|
||||
dayNameRow.push("", "Práce mimo směnu") // Empty separator + the text
|
||||
yearRow.push("", "") // Empty separator + empty for merged cell
|
||||
monthRow.push("", "") // Empty separator + empty for merged cell
|
||||
dateRow.push("", "") // Empty separator + empty for merged cell
|
||||
shiftRow.push("", "") // Empty separator + empty for merged cell
|
||||
|
||||
const employeeRows = employees.map(name => {
|
||||
const row = [name]
|
||||
// Add empty cells for each day/night pair
|
||||
@@ -119,7 +127,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
|
||||
// Sample data for different teams (fallback)
|
||||
const getTeamData = (_teamId: string) => {
|
||||
const getTeamData = (teamId: string) => {
|
||||
const baseData = [
|
||||
["Employee", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
||||
["John Smith", "08:00-16:00", "08:00-16:00", "08:00-16:00", "08:00-16:00", "08:00-16:00", "OFF", "OFF"],
|
||||
@@ -212,11 +220,11 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
console.log("Monthly data generated successfully")
|
||||
} else {
|
||||
console.log("Using basic team data")
|
||||
data = getTeamData(_teamId)
|
||||
data = getTeamData(teamId)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error generating data:", error)
|
||||
data = getTeamData(_teamId)
|
||||
data = getTeamData(teamId)
|
||||
}
|
||||
|
||||
console.log("Data generated:", data.length, "rows, first row:", data[0]?.length, "columns")
|
||||
@@ -249,7 +257,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
|
||||
// Style weekend days (Saturday/Sunday in day name row and date rows below)
|
||||
for (let col = 1; col < (data[0]?.length || 0); col += 2) {
|
||||
for (let col = 1; col < (data[0]?.length || 0) - 2; col += 2) { // -2 to exclude separator and Práce mimo směnu columns
|
||||
const dayName = data[1]?.[col]
|
||||
if (dayName === "Sobota" || dayName === "Neděle") {
|
||||
const colLetter = getExcelColumnName(col)
|
||||
@@ -266,6 +274,28 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Style the "Práce mimo směnu" column (last column)
|
||||
const totalCols = data[0]?.length || 0
|
||||
if (totalCols >= 2) {
|
||||
const separatorColIndex = totalCols - 2
|
||||
const praceMimoColIndex = totalCols - 1
|
||||
const separatorColLetter = getExcelColumnName(separatorColIndex)
|
||||
const praceMimoColLetter = getExcelColumnName(praceMimoColIndex)
|
||||
|
||||
// Style separator column with left border
|
||||
for (let row = 2; row <= 6; row++) {
|
||||
styles[`${separatorColLetter}${row}`] = "border-left: 2px solid #000000;"
|
||||
}
|
||||
|
||||
// Style "Práce mimo směnu" column
|
||||
styles[`${praceMimoColLetter}2`] = "border: 1px solid #000000; text-align: center; vertical-align: middle; font-weight: bold; height: 50px;"
|
||||
for (let row = 3; row <= 6; row++) {
|
||||
styles[`${praceMimoColLetter}${row}`] = "border-left: 1px solid #000000; border-right: 1px solid #000000;"
|
||||
}
|
||||
// Bottom border for the last row of the merged cell
|
||||
styles[`${praceMimoColLetter}6`] += " border-bottom: 1px solid #000000;"
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Initializing jspreadsheet with config:", {
|
||||
@@ -293,41 +323,64 @@ 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)
|
||||
setTimeout(() => {
|
||||
if (jspreadsheetInstance.current && selectedMonth && selectedYear) {
|
||||
const instance = jspreadsheetInstance.current as any
|
||||
if (instance.setMerge) {
|
||||
try {
|
||||
// Merge all pairs in rows 2, 3, 4, 5 (day names, year, month, day) excluding separator and Práce mimo směnu columns
|
||||
const totalCols = data[0]?.length || 0
|
||||
for (let row = 2; row <= 5; row++) {
|
||||
for (let col = 1; col < totalCols - 2; col += 2) { // -2 to exclude separator and Práce mimo směnu columns
|
||||
const colLetter = getExcelColumnName(col)
|
||||
try {
|
||||
// Correct syntax: setMerge(cellAddress, colspan, rowspan)
|
||||
instance.setMerge(`${colLetter}${row}`, 2, 1) // 2 columns, 1 row
|
||||
} catch (error) {
|
||||
// Silently skip merge errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge "Práce mimo směnu" column vertically from rows 2-6
|
||||
const praceMimoColIndex = totalCols - 1
|
||||
const praceMimoColLetter = getExcelColumnName(praceMimoColIndex)
|
||||
try {
|
||||
instance.setMerge(`${praceMimoColLetter}2`, 1, 5) // 1 column, 5 rows (2-6)
|
||||
} catch (error) {
|
||||
console.error("Error merging Práce mimo směnu column:", error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error during merging:", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
|
||||
// Apply counter-clockwise rotation to data values only (exclude second column which contains field labels)
|
||||
setTimeout(() => {
|
||||
const table = spreadsheetRef.current?.querySelector('.jexcel tbody')
|
||||
if (table) {
|
||||
const rows = table.querySelectorAll('tr')
|
||||
const totalCells = data[0]?.length || 0
|
||||
|
||||
// Rotate data values in rows 2, 3, 4, 5, 6 (day names, year, month, day, shifts) excluding first two columns
|
||||
// Rotate data values in rows 2, 3, 4, 5, 6 (day names, year, month, day, shifts)
|
||||
;[1, 2, 3, 4, 5].forEach(rowIndex => {
|
||||
if (rows[rowIndex]) {
|
||||
const cells = rows[rowIndex].querySelectorAll('td')
|
||||
cells.forEach((cell, cellIndex) => {
|
||||
// Skip first two columns (row numbers and field labels)
|
||||
if (cellIndex > 1) {
|
||||
const originalText = cell.textContent
|
||||
// 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>`
|
||||
// Skip first two columns (row numbers and field labels), separator column, but include Práce mimo směnu
|
||||
if (cellIndex > 1 && cellIndex < totalCells + 1) { // +1 because of row number column
|
||||
const originalText = cell.textContent?.trim()
|
||||
if (originalText) {
|
||||
// Special handling for "Práce mimo směnu" text
|
||||
if (originalText === "Práce mimo směnu") {
|
||||
cell.innerHTML = `<div style="transform: rotate(-90deg); font-size: 12px; height: 80px; display: flex; align-items: center; justify-content: center; white-space: nowrap; font-weight: bold;">${originalText}</div>`
|
||||
} else if (cellIndex < totalCells - 1) { // Don't rotate separator column (empty)
|
||||
// Use 12px font for all other 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>`
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -366,7 +419,7 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
jspreadsheetInstance.current.destroy()
|
||||
}
|
||||
}
|
||||
}, [_teamId, selectedMonth, selectedYear, forceUpdate])
|
||||
}, [teamId, selectedMonth, selectedYear, forceUpdate])
|
||||
|
||||
const handleSave = () => {
|
||||
if (jspreadsheetInstance.current) {
|
||||
@@ -400,11 +453,6 @@ export function TimeshiftSpreadsheet({ teamId: _teamId, teamName }: TimeshiftSpr
|
||||
}
|
||||
}
|
||||
|
||||
const handleAddEmployee = () => {
|
||||
if (jspreadsheetInstance.current) {
|
||||
jspreadsheetInstance.current.insertRow()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="w-full">
|
||||
|
||||
Reference in New Issue
Block a user