Files
Luncher/client/src/App.scss
T
mates f28f127a92
CI / Generate TypeScript types (push) Successful in 12s
CI / Server unit tests (push) Successful in 20s
CI / Build server (push) Successful in 24s
CI / Build client (push) Successful in 36s
CI / Playwright E2E tests (push) Successful in 1m17s
CI / Build and push Docker image (push) Successful in 40s
CI / Notify (push) Successful in 2s
feat: zvýraznění dnů v historii obsahujících objednávky
2026-06-05 14:50:33 +02:00

1228 lines
24 KiB
SCSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================
// DESIGN SYSTEM - LUNCHER APP
// ============================================
// Color palette - Spotify-style green scheme
:root, [data-bs-theme="light"] {
// Primary colors - Vibrant green
--luncher-primary: #16a34a;
--luncher-primary-hover: #15803d;
--luncher-primary-light: #dcfce7;
// Background colors
--luncher-bg: #f9fafb;
--luncher-bg-card: #ffffff;
--luncher-bg-hover: #f3f4f6;
// Text colors
--luncher-text: #111827;
--luncher-text-secondary: #4b5563;
--luncher-text-muted: #9ca3af;
// Border colors
--luncher-border: #e5e7eb;
--luncher-border-light: #f3f4f6;
// Navbar - Dark
--luncher-navbar-bg: #111827;
--luncher-navbar-text: #f9fafb;
// Action colors
--luncher-action-icon: #16a34a;
--luncher-buyer-icon: #d97706;
--luncher-success: #16a34a;
--luncher-warning: #d97706;
--luncher-danger: #dc2626;
// Shadows
--luncher-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--luncher-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--luncher-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
// Border radius
--luncher-radius-sm: 6px;
--luncher-radius: 10px;
--luncher-radius-lg: 12px;
--luncher-radius-xl: 16px;
// Transitions
--luncher-transition: all 0.2s ease;
--luncher-transition-slow: all 0.3s ease;
}
[data-bs-theme="dark"] {
// Primary colors - Spotify green
--luncher-primary: #1db954;
--luncher-primary-hover: #1ed760;
--luncher-primary-light: #052e16;
// Background colors - True dark like Spotify
--luncher-bg: #121212;
--luncher-bg-card: #181818;
--luncher-bg-hover: #282828;
// Text colors
--luncher-text: #ffffff;
--luncher-text-secondary: #b3b3b3;
--luncher-text-muted: #6b7280;
// Border colors
--luncher-border: #282828;
--luncher-border-light: #1f1f1f;
// Navbar
--luncher-navbar-bg: #000000;
--luncher-navbar-text: #ffffff;
// Action colors
--luncher-action-icon: #1db954;
--luncher-buyer-icon: #fbbf24;
--luncher-success: #1db954;
--luncher-warning: #fbbf24;
--luncher-danger: #f87171;
// Shadows
--luncher-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.5);
--luncher-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.5), 0 2px 4px -2px rgb(0 0 0 / 0.4);
--luncher-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.5), 0 4px 6px -4px rgb(0 0 0 / 0.4);
}
// ============================================
// BASE STYLES
// ============================================
html, body, #root {
height: 100%;
margin: 0;
}
html {
overflow-x: hidden;
}
body {
background-color: var(--luncher-bg);
color: var(--luncher-text);
transition: var(--luncher-transition-slow);
}
// ============================================
// APP CONTAINER
// ============================================
.app-container {
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: var(--luncher-bg);
}
.wrapper {
padding: 24px;
flex: 1;
max-width: 1400px;
margin: 0 auto;
width: 100%;
@media (max-width: 768px) {
padding: 16px;
}
}
// ============================================
// NAVBAR
// ============================================
.navbar {
background: var(--luncher-navbar-bg) !important;
padding: 12px 24px;
box-shadow: none;
border: none;
border-bottom: 1px solid var(--luncher-border);
.navbar-brand {
font-weight: 700;
font-size: 1.5rem;
letter-spacing: -0.5px;
color: var(--luncher-navbar-text) !important;
transition: var(--luncher-transition);
&:hover {
opacity: 0.9;
}
}
.nav-link, .dropdown-toggle {
color: var(--luncher-navbar-text) !important;
font-weight: 500;
transition: var(--luncher-transition);
&:hover {
opacity: 0.85;
}
}
.dropdown-menu {
background: var(--luncher-bg-card);
border: 1px solid var(--luncher-border);
border-radius: var(--luncher-radius);
box-shadow: var(--luncher-shadow-lg);
padding: 8px;
margin-top: 8px;
.dropdown-item {
color: var(--luncher-text);
border-radius: var(--luncher-radius-sm);
padding: 10px 16px;
transition: var(--luncher-transition);
font-weight: 500;
&:hover {
background: var(--luncher-bg-hover);
color: var(--luncher-primary);
}
}
.dropdown-divider {
border-color: var(--luncher-border);
margin: 8px 0;
}
}
}
#basic-navbar-nav {
justify-content: flex-end;
}
// Theme toggle button
.theme-toggle {
background: transparent;
border: none;
color: var(--luncher-navbar-text);
padding: 8px 12px;
margin-right: 16px;
border-radius: var(--luncher-radius-sm);
cursor: pointer;
transition: var(--luncher-transition);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.1rem;
&:hover {
background: rgba(255, 255, 255, 0.1);
transform: scale(1.1);
}
&:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}
svg {
transition: transform 0.3s ease;
}
&:hover svg {
transform: rotate(15deg);
}
}
// ============================================
// TYPOGRAPHY & TITLES
// ============================================
.title {
margin: 32px 0;
font-weight: 700;
font-size: 2rem;
color: var(--luncher-text);
&.text-muted {
color: var(--luncher-text-muted) !important;
}
}
// ============================================
// DAY NAVIGATOR
// ============================================
.day-navigator {
display: flex;
align-items: center;
justify-content: center;
gap: 24px;
margin-bottom: 32px;
svg {
font-size: 1.5rem;
color: var(--luncher-text-secondary);
cursor: pointer;
padding: 12px;
border-radius: 50%;
background: var(--luncher-bg-card);
box-shadow: var(--luncher-shadow-sm);
transition: var(--luncher-transition);
&:hover {
color: var(--luncher-primary);
background: var(--luncher-primary-light);
transform: scale(1.05);
}
}
h1 {
margin: 0;
min-width: 300px;
text-align: center;
}
}
// Varianta navigace mezi dny na stránce objednávání šipky kolem date pickeru
.order-day-navigator {
margin-bottom: 16px;
gap: 16px;
// react-datepicker obaluje input do wrapperu necháme ho zabrat jen potřebnou šířku
.react-datepicker-wrapper {
width: auto;
}
.order-date-input {
width: 160px;
cursor: pointer;
}
}
// Zvýraznění dnů, ve kterých existuje alespoň jedna objednávka tečka pod číslem dne
.react-datepicker__day.luncher-order-day {
position: relative;
font-weight: 700;
&::after {
content: "";
position: absolute;
left: 50%;
bottom: 2px;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--luncher-primary, #0d6efd);
}
// U vybraného dne (tmavé pozadí) je tečka světlá, aby byla vidět
&.react-datepicker__day--selected::after,
&.react-datepicker__day--keyboard-selected::after {
background: #fff;
}
}
// Vybraný den používá akcentovou barvu aplikace (v obou režimech), místo výchozí modré
.react-datepicker__day--selected,
.react-datepicker__day--keyboard-selected {
background-color: var(--luncher-primary);
color: #fff;
&:hover {
background-color: var(--luncher-primary-hover);
}
}
// Tmavý režim kalendáře (react-datepicker) navázáno na CSS proměnné motivu
[data-bs-theme="dark"] {
.react-datepicker {
background-color: var(--luncher-bg-card);
border-color: var(--luncher-border);
color: var(--luncher-text);
}
.react-datepicker__header {
background-color: var(--luncher-bg-hover);
border-bottom-color: var(--luncher-border);
}
.react-datepicker__current-month,
.react-datepicker__day-name,
.react-datepicker__day,
.react-datepicker-year-header {
color: var(--luncher-text);
}
.react-datepicker__day:hover,
.react-datepicker__month-text:hover {
background-color: var(--luncher-bg-hover);
}
.react-datepicker__day--today {
color: var(--luncher-primary);
}
.react-datepicker__day--disabled,
.react-datepicker__day--outside-month {
color: var(--luncher-text-muted);
}
// Šipky pro přepínání měsíců
.react-datepicker__navigation-icon::before {
border-color: var(--luncher-text-secondary);
}
// Špička popoveru (SVG) míří do hlavičky sladíme barvy.
// !important kvůli vyšší specificitě knihovního pravidla [data-placement].
.react-datepicker__triangle {
fill: var(--luncher-bg-hover) !important;
color: var(--luncher-bg-hover) !important;
stroke: var(--luncher-border) !important;
}
}
// ============================================
// FOOD TABLES - CARD STYLE
// ============================================
.food-tables {
margin-bottom: 48px;
display: flex;
flex-wrap: wrap;
> [class*="col-"] {
margin-bottom: 24px;
display: flex;
}
}
.restaurant-card {
background: var(--luncher-bg-card);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
overflow: hidden;
width: 100%;
display: flex;
flex-direction: column;
transition: var(--luncher-transition);
border: 1px solid var(--luncher-border-light);
&:hover {
box-shadow: var(--luncher-shadow-lg);
transform: translateY(-2px);
}
.restaurant-header {
background: var(--luncher-primary);
padding: 16px 20px;
border-bottom: none;
cursor: pointer;
transition: var(--luncher-transition);
display: flex;
align-items: center;
gap: 8px;
&:hover {
background: var(--luncher-primary-hover);
}
.restaurant-header-content {
display: flex;
flex-direction: column;
flex: 1;
}
h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
color: #ffffff;
cursor: pointer;
}
small {
display: block;
margin-top: 4px;
color: rgba(255, 255, 255, 0.7);
font-size: 0.75rem;
}
.restaurant-warning {
color: #f59e0b;
cursor: help;
font-size: 1rem;
}
}
.restaurant-closed {
padding: 40px 20px;
text-align: center;
color: var(--luncher-text-muted);
font-weight: 500;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.restaurant-error {
padding: 40px 20px;
text-align: center;
color: var(--luncher-danger);
font-weight: 500;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.food-table {
flex: 1;
}
}
.food-table {
margin: 0;
tbody tr {
transition: var(--luncher-transition);
cursor: pointer;
&:hover {
background: var(--luncher-bg-hover);
.food-name {
color: var(--luncher-primary);
}
}
&:last-child td {
border-bottom: none;
}
}
td {
padding: 12px 16px;
border-color: var(--luncher-border-light);
vertical-align: middle;
color: var(--luncher-text);
}
.food-name {
font-weight: 500;
margin-bottom: 4px;
}
.food-allergens {
white-space: nowrap;
}
.food-meta {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 12px;
margin-top: 6px;
font-size: 0.75rem;
}
.food-amount {
color: var(--luncher-text-muted);
font-weight: 400;
}
.food-price {
font-weight: 600;
color: var(--luncher-primary);
}
.allergen-link {
cursor: help;
text-decoration: underline;
text-decoration-style: dotted;
color: var(--luncher-text-muted);
font-size: 0.95em;
&:hover {
color: var(--luncher-primary);
}
}
}
// ============================================
// CHOICE FORM
// ============================================
.content-wrapper {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.content {
width: 100%;
max-width: 700px;
}
.choice-section {
background: var(--luncher-bg-card);
border-radius: var(--luncher-radius);
padding: 16px 20px;
box-shadow: var(--luncher-shadow-sm);
margin-bottom: 24px;
border: 1px solid var(--luncher-border-light);
p {
margin-bottom: 8px;
font-weight: 500;
color: var(--luncher-text);
font-size: 0.95rem;
}
small {
display: block;
margin-top: 6px;
color: var(--luncher-text-muted);
font-size: 0.8rem;
}
}
// ============================================
// FORM CONTROLS
// ============================================
.form-select, .form-control {
background-color: var(--luncher-bg);
border: 2px solid var(--luncher-border);
border-radius: var(--luncher-radius-sm);
padding: 12px 16px;
font-size: 1rem;
color: var(--luncher-text);
transition: var(--luncher-transition);
&:hover {
border-color: var(--luncher-text-muted);
}
&:focus {
border-color: var(--luncher-primary);
box-shadow: 0 0 0 3px var(--luncher-primary-light);
outline: none;
}
}
input[type="text"], input[type="email"], input[type="password"] {
background-color: var(--luncher-bg);
border: 2px solid var(--luncher-border);
border-radius: var(--luncher-radius-sm);
padding: 12px 16px;
font-size: 1rem;
color: var(--luncher-text);
transition: var(--luncher-transition);
width: 100%;
&:hover {
border-color: var(--luncher-text-muted);
}
&:focus {
border-color: var(--luncher-primary);
box-shadow: 0 0 0 3px var(--luncher-primary-light);
outline: none;
}
&::placeholder {
color: var(--luncher-text-muted);
}
}
// ============================================
// BUTTONS
// ============================================
.btn {
border-radius: var(--luncher-radius-sm);
padding: 12px 24px;
font-weight: 600;
transition: var(--luncher-transition);
border: none;
&:focus {
box-shadow: 0 0 0 3px var(--luncher-primary-light);
}
}
.btn-primary {
background: var(--luncher-primary);
color: white;
&:hover {
background: var(--luncher-primary-hover);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
}
.btn-secondary {
background: var(--luncher-bg-hover);
color: var(--luncher-text);
&:hover {
background: var(--luncher-border);
}
}
.btn-danger, .btn.danger {
background: var(--luncher-danger);
color: white;
&:hover {
background: #dc2626;
}
}
.btn-outline-primary {
background: transparent;
border: 2px solid var(--luncher-primary);
color: var(--luncher-primary);
&:hover {
background: var(--luncher-primary);
color: white;
}
}
// ============================================
// CHOICES TABLE
// ============================================
.choices-table {
background: var(--luncher-bg-card);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
overflow: hidden;
border: 1px solid var(--luncher-border-light);
> tbody > tr {
&:last-child > td {
border-bottom: none;
}
> td {
padding: 0;
border-color: var(--luncher-border);
vertical-align: middle;
&:first-child {
background: var(--luncher-primary-light);
padding: 16px 20px;
font-weight: 600;
color: var(--luncher-primary);
width: 180px;
white-space: nowrap;
@media (max-width: 576px) {
width: 120px;
padding: 12px 16px;
font-size: 0.9rem;
}
}
}
}
.nested-table {
margin: 0;
tbody tr {
transition: var(--luncher-transition);
border-bottom: 1px solid var(--luncher-border-light);
&:hover {
background: var(--luncher-bg-hover);
}
&:last-child {
border-bottom: none;
td {
border-bottom: none;
}
}
}
td {
padding: 12px 16px;
border: none;
color: var(--luncher-text);
vertical-align: middle;
}
.user-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.user-info {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.user-actions {
display: flex;
gap: 8px;
align-items: center;
white-space: nowrap;
}
}
.food-choices {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 8px;
}
.food-choice-item {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.85rem;
color: var(--luncher-text-secondary);
.action-icon {
opacity: 0;
transition: var(--luncher-transition);
}
&:hover .action-icon {
opacity: 1;
}
}
.food-choice-name {
color: var(--luncher-text-secondary);
font-weight: 400;
}
}
.no-votes {
text-align: center;
padding: 48px 24px;
color: var(--luncher-text-muted);
font-style: italic;
background: var(--luncher-bg-card);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow);
}
// ============================================
// ACTION ICONS
// ============================================
.action-icon {
color: var(--luncher-action-icon);
cursor: pointer;
margin-left: 12px;
padding: 4px;
border-radius: 4px;
transition: var(--luncher-transition);
&:hover {
background: var(--luncher-primary-light);
transform: scale(1.1);
}
}
.buyer-icon {
color: var(--luncher-buyer-icon);
margin-left: 12px;
padding: 4px;
}
.trusted-icon {
color: var(--luncher-success);
margin-right: 8px;
}
// ============================================
// PIZZA DAY SECTION
// ============================================
.pizza-section {
background: var(--luncher-bg-card);
border-radius: var(--luncher-radius-lg);
padding: 32px;
box-shadow: var(--luncher-shadow);
text-align: center;
margin-top: 48px;
border: 1px solid var(--luncher-border-light);
h3 {
color: var(--luncher-primary);
font-weight: 700;
margin-bottom: 16px;
}
p {
color: var(--luncher-text-secondary);
margin-bottom: 24px;
}
.btn + .btn {
margin-left: 16px;
}
}
.pizza-order-form {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: center;
align-items: center;
margin-top: 24px;
input[type="text"] {
width: auto;
min-width: 200px;
}
}
// ============================================
// QR CODE
// ============================================
.qr-code {
text-align: center;
margin-top: 32px;
padding: 24px;
background: var(--luncher-bg);
border-radius: var(--luncher-radius);
h3 {
color: var(--luncher-text);
margin-bottom: 16px;
}
img {
border-radius: var(--luncher-radius-sm);
box-shadow: var(--luncher-shadow);
}
}
// ============================================
// ALERT
// ============================================
.alert {
border-radius: var(--luncher-radius);
border: none;
box-shadow: var(--luncher-shadow-sm);
position: relative;
overflow: visible;
&.alert-primary {
background: var(--luncher-primary-light);
color: var(--luncher-primary);
border-left: 4px solid var(--luncher-primary);
}
ul {
margin-bottom: 0;
padding-left: 20px;
li {
margin-bottom: 4px;
}
}
}
// ============================================
// LOADER
// ============================================
.loader {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--luncher-bg);
padding: 24px;
.loader-icon {
font-size: 64px;
color: var(--luncher-primary);
margin-bottom: 24px;
}
.loader-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--luncher-text);
margin-bottom: 12px;
}
.loader-description {
color: var(--luncher-text-secondary);
max-width: 400px;
text-align: center;
line-height: 1.6;
}
}
// ============================================
// SELECT SEARCH
// ============================================
.select-search-container {
margin: auto;
.select-search-input {
background: var(--luncher-bg);
border: 2px solid var(--luncher-border);
border-radius: var(--luncher-radius-sm);
padding: 12px 16px;
font-size: 1rem;
color: var(--luncher-text);
height: auto;
&:focus {
border-color: var(--luncher-primary);
box-shadow: 0 0 0 3px var(--luncher-primary-light);
}
}
.select-search-select {
background: var(--luncher-bg-card);
border: 1px solid var(--luncher-border);
border-radius: var(--luncher-radius);
box-shadow: var(--luncher-shadow-lg);
overflow: hidden;
}
.select-search-option {
padding: 12px 16px;
color: var(--luncher-text);
&:hover, &.is-selected {
background: var(--luncher-primary-light);
color: var(--luncher-primary);
}
}
.select-search-group-header {
background: var(--luncher-bg-hover);
color: var(--luncher-text-secondary);
font-weight: 600;
padding: 8px 16px;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
}
// ============================================
// FOOTER
// ============================================
.footer {
background: var(--luncher-navbar-bg);
color: var(--luncher-navbar-text);
padding: 16px 24px;
text-align: center;
margin-top: auto;
flex-shrink: 0;
font-size: 0.9rem;
a {
color: var(--luncher-primary);
transition: var(--luncher-transition);
&:hover {
color: var(--luncher-primary-hover);
}
}
}
// ============================================
// ANIMATIONS
// ============================================
@keyframes bounce-in {
0% {
left: var(--start-left);
right: var(--start-right);
top: var(--start-top);
bottom: var(--start-bottom);
}
25% {
left: var(--end-left);
right: var(--end-right);
top: var(--end-top);
bottom: var(--end-bottom);
}
50% {
left: var(--start-left);
right: var(--start-right);
top: var(--start-top);
bottom: var(--start-bottom);
}
75% {
left: var(--end-left);
right: var(--end-right);
top: var(--end-top);
bottom: var(--end-bottom);
}
100% {
left: var(--start-left);
right: var(--start-right);
top: var(--start-top);
bottom: var(--start-bottom);
}
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.3s ease;
}
// ============================================
// UTILITIES
// ============================================
.text-muted {
color: var(--luncher-text-muted) !important;
}
.mt-3 { margin-top: 16px !important; }
.mt-5 { margin-top: 32px !important; }
.mb-3 { margin-bottom: 16px !important; }
.mb-5 { margin-bottom: 32px !important; }
// ============================================
// MODALS
// ============================================
.modal-content {
background: var(--luncher-bg-card);
border: 1px solid var(--luncher-border);
border-radius: var(--luncher-radius-lg);
box-shadow: var(--luncher-shadow-lg);
}
.modal-header {
border-bottom: 1px solid var(--luncher-border);
padding: 20px 24px;
.modal-title {
h2 {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
color: var(--luncher-text);
}
}
.btn-close {
opacity: 0.5;
transition: var(--luncher-transition);
&:hover {
opacity: 1;
}
}
}
.modal-body {
padding: 24px;
color: var(--luncher-text);
h4 {
font-size: 1rem;
font-weight: 600;
color: var(--luncher-primary);
margin-bottom: 12px;
}
p {
color: var(--luncher-text-secondary);
font-size: 0.9rem;
line-height: 1.6;
}
hr {
border-color: var(--luncher-border);
margin: 20px 0;
}
.form-label {
font-weight: 500;
color: var(--luncher-text);
margin-bottom: 8px;
}
}
.modal-footer {
border-top: 1px solid var(--luncher-border);
padding: 16px 24px;
gap: 12px;
}
// ============================================
// LEGACY COMPATIBILITY
// ============================================
.App {
text-align: center;
}
.table {
margin-bottom: 0;
color: var(--luncher-text);
> :not(caption) {
.action-icon {
color: var(--luncher-action-icon);
cursor: pointer;
margin-left: 10px;
padding: 0;
}
.buyer-icon {
color: var(--luncher-buyer-icon);
margin-left: 10px;
padding: 0;
}
}
ul {
padding: 0;
margin-left: 20px;
margin-bottom: 0;
}
td {
vertical-align: top;
}
> tbody > tr > td > table > tbody > tr > td {
border: none;
}
}