feat(frontend): race form, start time selects, calendar views, day page
Some checks failed
CI / build-and-test (pull_request) Has been cancelled

- Hide org schedule fields when editing a past race; isRaceDateInPast helper
- StartTimeSelects (HH:mm:ss) and optional ?date= prefill on new race
- Full-card link to edit for races needing result entry; shadow token
- List/calendar toggle (sessionStorage); year grid and month focus views
- Date hover popover and /races/day/:ymd page with Add button
- Docs plan-korrektirovok-starty.md and startTime API note; client 0.4.0

Made-with: Cursor
This commit is contained in:
Vaka.pro
2026-04-13 22:07:37 +03:00
parent b997dcb01e
commit 3c6baa66a1
16 changed files with 1193 additions and 69 deletions

View File

@@ -295,6 +295,37 @@ a {
outline: 1px solid var(--color-warning);
}
.race-card--action {
padding: 0;
overflow: visible;
}
.race-card__link-surface {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--space-3);
width: 100%;
padding: var(--space-3);
border-radius: var(--radius-sm);
color: inherit;
text-decoration: none;
transition:
transform 0.15s ease,
box-shadow 0.15s ease;
}
.race-card--action:hover .race-card__link-surface,
.race-card--action:focus-within .race-card__link-surface {
transform: scale(1.02);
box-shadow: var(--shadow-card-lift);
outline: none;
}
.race-card__title-text {
font-weight: 600;
}
.race-details-past-hint {
margin: 0 0 var(--space-4);
padding: var(--space-3) var(--space-4);
@@ -598,6 +629,35 @@ a {
min-height: 5rem;
}
.race-form__time-picker {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: var(--space-2);
}
.race-form__time-picker__unit {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.race-form__time-picker__label {
font-size: var(--font-size-caption);
font-weight: 600;
color: var(--color-text-muted);
}
.race-form__time-picker__select {
min-width: 4.25rem;
}
.race-form__time-picker__sep {
color: var(--color-text-muted);
font-weight: 600;
padding-bottom: var(--space-2);
}
.race-form__actions {
display: flex;
gap: var(--space-3);
@@ -618,6 +678,286 @@ a {
margin: var(--space-1) 0;
}
.races-view-toggle {
display: inline-flex;
margin-top: var(--space-5);
padding: var(--space-1);
border-radius: var(--radius-md);
border: 1px solid var(--color-border);
background: var(--color-surface);
gap: var(--space-1);
}
.races-view-toggle__btn {
font: inherit;
font-size: var(--font-size-caption);
font-weight: 600;
padding: var(--space-2) var(--space-4);
border: none;
border-radius: var(--radius-sm);
background: transparent;
color: var(--color-text-muted);
cursor: pointer;
}
.races-view-toggle__btn:hover,
.races-view-toggle__btn:focus-visible {
color: var(--color-text);
outline: none;
}
.races-view-toggle__btn--active {
background: #eef2f6;
color: var(--color-text);
}
.races-cal-wrap {
margin-top: var(--space-6);
}
.races-cal__filter-hint {
margin-top: var(--space-3);
color: var(--color-text-muted);
font-size: var(--font-size-caption);
}
.races-cal__hint {
margin: 0 0 var(--space-4);
color: var(--color-text-muted);
font-size: var(--font-size-caption);
}
.races-cal__year {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
gap: var(--space-5);
}
.races-cal__month {
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: var(--space-3);
background: var(--color-surface);
}
.races-cal__month--compact .races-cal__month-title {
font-size: var(--font-size-caption);
}
.races-cal__month--compact .races-cal__weekday {
font-size: 0.65rem;
}
.races-cal__month--compact .races-cal__day-btn {
font-size: var(--font-size-caption);
min-height: 1.65rem;
}
.races-cal__month-title {
margin: 0 0 var(--space-2);
font-size: var(--font-size-body);
font-weight: 600;
color: var(--color-text);
}
.races-cal__weekdays {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 1px;
margin-bottom: var(--space-1);
}
.races-cal__weekday {
font-size: var(--font-size-caption);
font-weight: 600;
color: var(--color-text-muted);
text-align: center;
}
.races-cal__cells {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 2px;
}
.races-cal__cell {
position: relative;
min-height: 2rem;
}
.races-cal__cell--empty {
min-height: 0;
}
.races-cal__cell--has-race .races-cal__day-btn {
font-weight: 700;
color: var(--color-accent);
}
.races-cal__cell--open {
z-index: 2;
}
.races-cal__day-btn {
width: 100%;
height: 100%;
min-height: 2rem;
font: inherit;
font-size: var(--font-size-caption);
border: 1px solid transparent;
border-radius: var(--radius-sm);
background: transparent;
color: var(--color-text);
cursor: pointer;
}
.races-cal__day-btn:hover,
.races-cal__day-btn:focus-visible {
background: #eef2f6;
border-color: var(--color-border);
outline: none;
}
.races-cal__cell--has-race .races-cal__day-btn:hover,
.races-cal__cell--has-race .races-cal__day-btn:focus-visible {
background: #e8f0fc;
border-color: var(--color-accent);
}
.races-cal__popover {
position: absolute;
top: calc(100% + var(--space-1));
left: 50%;
transform: translateX(-50%);
min-width: 11rem;
max-width: 16rem;
padding: var(--space-3);
border-radius: var(--radius-sm);
border: 1px solid var(--color-border);
background: var(--color-surface);
box-shadow: var(--shadow-card-lift);
z-index: 5;
}
.races-cal__popover-list {
margin: 0 0 var(--space-2);
padding: 0;
list-style: none;
}
.races-cal__popover-item {
margin: 0 0 var(--space-1);
}
.races-cal__popover-link {
color: var(--color-accent);
font-weight: 600;
font-size: var(--font-size-caption);
text-decoration: none;
}
.races-cal__popover-link:hover,
.races-cal__popover-link:focus-visible {
text-decoration: underline;
outline: none;
}
.races-cal__popover-empty {
margin: 0 0 var(--space-2);
font-size: var(--font-size-caption);
color: var(--color-text-muted);
}
.races-cal__popover-add {
width: 100%;
justify-content: center;
text-align: center;
font-size: var(--font-size-caption);
padding: var(--space-2);
}
.races-cal__month-focus .races-cal__month {
max-width: 28rem;
margin-top: var(--space-4);
}
.races-cal__month-nav {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-top: var(--space-4);
}
.races-cal__month-nav-item {
font: inherit;
font-size: var(--font-size-caption);
padding: var(--space-1) var(--space-2);
border: none;
border-radius: var(--radius-sm);
background: transparent;
color: var(--color-accent);
cursor: pointer;
text-decoration: underline;
text-underline-offset: 2px;
}
.races-cal__month-nav-item:hover,
.races-cal__month-nav-item:focus-visible {
outline: none;
color: var(--color-text);
}
.races-cal__month-nav-item--active {
font-weight: 700;
text-decoration: none;
background: #eef2f6;
color: var(--color-text);
}
.races-cal__month-nav-item--all {
color: var(--color-text-muted);
}
.race-day__list {
margin: var(--space-5) 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.race-day__item {
display: flex;
flex-direction: column;
gap: var(--space-1);
padding: var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-surface);
}
.race-day__link {
font-weight: 600;
color: var(--color-accent);
text-decoration: none;
}
.race-day__link:hover,
.race-day__link:focus-visible {
text-decoration: underline;
outline: none;
}
.race-day__meta {
font-size: var(--font-size-caption);
color: var(--color-text-muted);
}
.race-day__actions {
margin-top: var(--space-5);
}
/* ─── Responsive ───────────────────────────────────────── */
@media (max-width: 900px) {