feat: create DayTabs date carousel component

This commit is contained in:
gnezim
2026-04-05 20:56:42 +03:00
parent b5bdd1e18d
commit 3225ecd1fa
4 changed files with 114 additions and 12 deletions
+13 -12
View File
@@ -8,25 +8,26 @@
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.15.0",
"primereact": "^10.0.0",
"primeicons": "^6.0.0",
"leaflet": "^1.7.1",
"@tanstack/react-query": "^5.28.0",
"axios": "^1.6.0",
"date-fns": "^4.1.0",
"i18next": "^23.7.0",
"i18next-http-backend": "^2.4.0",
"leaflet": "^1.7.1",
"primeicons": "^6.0.0",
"primereact": "^10.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.5.0",
"axios": "^1.6.0",
"@tanstack/react-query": "^5.28.0",
"react-router-dom": "^6.15.0",
"zustand": "^4.4.0"
},
"devDependencies": {
"vite": "^5.0.0",
"@vitejs/plugin-react": "^4.2.0",
"typescript": "^5.3.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"sass": "^1.69.0"
"@vitejs/plugin-react": "^4.2.0",
"sass": "^1.69.0",
"typescript": "^5.3.0",
"vite": "^5.0.0"
}
}
@@ -0,0 +1,40 @@
.day-tabs {
margin: 20px 0;
}
.day-tabs__day {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px;
border: 1px solid #e0e0e0;
border-radius: 4px;
background: white;
cursor: pointer;
transition: all 0.2s ease;
min-width: 60px;
&:hover {
border-color: #1976d2;
color: #1976d2;
}
&--active {
background: #1976d2;
color: white;
border-color: #1976d2;
}
}
.day-tabs__day-name {
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
margin-bottom: 4px;
}
.day-tabs__day-num {
font-size: 18px;
font-weight: 600;
}
@@ -0,0 +1,59 @@
import React from 'react'
import { Carousel } from 'primereact/carousel'
import { format, addDays, startOfDay } from 'date-fns'
import './day-tabs.scss'
export interface DayTabsProps {
selectedDate: Date
onDateSelect: (date: Date) => void
minDate?: Date
maxDate?: Date
'data-testid'?: string
}
export const DayTabs: React.FC<DayTabsProps> = ({
selectedDate,
onDateSelect,
'data-testid': dataTestId,
}) => {
const getDays = () => {
const days = []
for (let i = 0; i < 7; i++) {
days.push(startOfDay(addDays(new Date(), i)))
}
return days
}
const days = getDays()
const dayItemTemplate = (day: Date) => {
const isSelected = format(day, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd')
const dayName = format(day, 'EEE')
const dayNum = format(day, 'd')
return (
<button
className={`day-tabs__day ${isSelected ? 'day-tabs__day--active' : ''}`}
onClick={() => onDateSelect(day)}
data-testid={`day-tab-${format(day, 'yyyy-MM-dd')}`}
>
<div className="day-tabs__day-name">{dayName}</div>
<div className="day-tabs__day-num">{dayNum}</div>
</button>
)
}
return (
<div className="day-tabs" data-testid={dataTestId || 'day-tabs'}>
<Carousel
value={days}
itemTemplate={dayItemTemplate}
numScroll={3}
numVisible={7}
circular={false}
showNavigators={true}
/>
</div>
)
}
@@ -0,0 +1,2 @@
export { DayTabs } from './day-tabs'
export type { DayTabsProps } from './day-tabs'