style changes

This commit is contained in:
sdarbinyan
2026-02-14 02:34:11 +04:00
parent 751ad48489
commit 4238d59fc6
20 changed files with 1448 additions and 1032 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@
/tmp
/out-tsc
/bazel-out
/files
# Node
/node_modules

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@@ -73,7 +73,7 @@
</div>
</nav>
<!-- Search Box -->
<!-- Search Box (desktop) -->
<div class="dexar-search-wrapper">
<div class="dexar-search-box">
<svg class="dexar-search-icon" width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -84,6 +84,14 @@
</div>
</div>
<!-- Search Icon (mobile only) -->
<button class="dexar-search-mobile" (click)="navigateToSearch()" aria-label="Поиск">
<svg width="22" height="22" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#1e3c38" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#1e3c38" />
</svg>
</button>
<!-- Right Actions -->
<div class="dexar-actions">
<!-- Cart Button -->

View File

@@ -78,12 +78,12 @@
&:hover {
color: var(--primary-hover);
background: rgba(85, 104, 211, 0.05);
background: rgba(73, 118, 113, 0.05);
}
&.active {
color: var(--primary-hover);
background: rgba(85, 104, 211, 0.1);
background: rgba(73, 118, 113, 0.1);
font-weight: 600;
}
}
@@ -183,11 +183,11 @@
}
&:hover {
background: rgba(85, 104, 211, 0.05);
background: rgba(73, 118, 113, 0.05);
}
&.active {
background: rgba(85, 104, 211, 0.1);
background: rgba(73, 118, 113, 0.1);
}
}
@@ -458,6 +458,7 @@
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.dexar-header-container {
@@ -585,14 +586,14 @@
.dexar-actions {
display: flex;
align-items: center;
gap: 4px;
gap: 8px;
flex-shrink: 0;
}
.dexar-cart-btn {
position: relative;
width: 32px;
height: 24px;
width: 36px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
@@ -601,8 +602,8 @@
transition: opacity 0.3s ease;
svg {
width: 32px;
height: 24px;
width: 36px;
height: 28px;
}
&:hover {
@@ -616,18 +617,21 @@
.dexar-cart-badge {
position: absolute;
top: -6px;
right: -6px;
background: linear-gradient(135deg, #ff4757 0%, #ff6b81 100%);
color: white;
top: -8px;
right: -10px;
background: #497671;
color: #ffffff;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 700;
font-size: 0.75rem;
padding: 2px 6px;
border-radius: 10px;
min-width: 18px;
text-align: center;
box-shadow: 0 2px 6px rgba(255, 71, 87, 0.4);
border: 2px solid white;
font-size: 10px;
line-height: 1;
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.dexar-lang-selector {
@@ -667,6 +671,23 @@
}
}
// Mobile Search Icon
.dexar-search-mobile {
display: none;
align-items: center;
justify-content: center;
background: none;
border: none;
cursor: pointer;
padding: 6px;
margin-left: auto;
transition: opacity 0.2s ease;
&:hover {
opacity: 0.7;
}
}
// Responsive Design
@media (max-width: 1200px) {
.dexar-header-container {
@@ -777,22 +798,11 @@
}
.dexar-search-wrapper {
flex: 1;
max-width: none;
margin-left: 0;
display: none;
}
.dexar-search-box {
height: 40px;
}
.dexar-search-icon {
width: 20px;
height: 20px;
}
.dexar-search-input {
font-size: 16px;
.dexar-search-mobile {
display: flex;
}
.dexar-menu-toggle {

View File

@@ -3,6 +3,7 @@
padding: 2rem 0;
max-width: 1400px;
margin: 0 auto;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
::ng-deep {
// PrimeNG carousel wrapper
@@ -21,8 +22,8 @@
height: 3rem;
border-radius: 50%;
background: white;
border: 2px solid #e5e7eb;
color: #374151;
border: 2px solid #d3dad9;
color: #1e3c38;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
align-self: center;
@@ -31,13 +32,13 @@
&:hover {
background: #f9fafb;
border-color: #d1d5db;
border-color: #d3dad9;
transform: scale(1.05);
}
&:not(:disabled):hover {
background: var(--primary-color, #5568d3);
border-color: var(--primary-color, #5568d3);
background: var(--primary-color, #497671);
border-color: var(--primary-color, #497671);
color: white;
}
}
@@ -63,7 +64,7 @@
flex-shrink: 0;
}
// Pagination dots - using actual PrimeNG rendered classes
// Pagination dots
.p-carousel-indicator-list {
display: flex !important;
justify-content: center !important;
@@ -79,20 +80,20 @@
width: 12px !important;
height: 12px !important;
border-radius: 50% !important;
background-color: #d1d5db !important;
background-color: #d3dad9 !important;
border: 0 !important;
padding: 0 !important;
cursor: pointer !important;
transition: all 0.3s ease !important;
&:hover {
background-color: #9ca3af !important;
background-color: #a1b4b5 !important;
transform: scale(1.2);
}
}
&.p-carousel-indicator-active .p-carousel-indicator-button {
background-color: var(--primary-color, #5568d3) !important;
background-color: var(--primary-color, #497671) !important;
width: 32px !important;
border-radius: 6px !important;
}
@@ -106,14 +107,14 @@
.carousel-empty {
text-align: center;
padding: 3rem 1rem;
color: #666;
color: #697777;
.spinner {
width: 40px;
height: 40px;
margin: 0 auto 1rem;
border: 4px solid #f3f3f3;
border-top: 4px solid var(--primary-color, #5568d3);
border-top: 4px solid var(--primary-color, #497671);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@@ -124,12 +125,13 @@
100% { transform: rotate(360deg); }
}
// Item card styles matching your existing design
// Item card styles
.item-card {
background: white;
border-radius: 12px;
border-radius: 13px;
border: 1px solid #d3dad9;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
position: relative;
height: 100%;
@@ -140,7 +142,7 @@
margin: 0 auto;
&:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
}
@@ -159,7 +161,7 @@
height: 140px;
overflow: hidden;
background: #f5f5f5;
border-radius: 12px;
border-radius: 13px;
img {
width: 100%;
@@ -181,10 +183,10 @@
position: absolute;
top: 12px;
right: 12px;
background: #e74c3c;
background: #ef4444;
color: white;
padding: 0.4rem 0.8rem;
border-radius: 6px;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 700;
z-index: 10;
@@ -211,11 +213,11 @@
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
color: #1a1a1a;
color: #1e3c38;
transition: color 0.2s;
&:hover {
color: var(--primary-color, #5568d3);
color: var(--primary-color, #497671);
}
}
@@ -226,12 +228,12 @@
font-size: 0.75rem;
.rating-stars {
color: #fbbf24;
color: #497671;
font-weight: 600;
}
.rating-count {
color: #6b7280;
color: #697777;
}
}
@@ -253,26 +255,26 @@
.discounted-price {
font-size: 0.9375rem;
font-weight: 700;
color: #1a1a1a;
color: #1e3c38;
}
.discounted-price {
color: #e74c3c;
color: #ef4444;
}
.original-price {
font-size: 0.8125rem;
color: #9ca3af;
color: #697777;
text-decoration: line-through;
}
}
.cart-icon-btn {
padding: 0.5rem;
background: var(--primary-color, #5568d3);
background: var(--primary-color, #497671);
color: white;
border: none;
border-radius: 8px;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
@@ -285,7 +287,7 @@
}
&:hover {
background: var(--primary-hover, #4456b3);
background: var(--primary-hover, #3d635f);
transform: scale(1.05);
}
@@ -301,14 +303,14 @@
.p-carousel-prev,
.p-carousel-next {
&:not(:disabled):hover {
background: var(--primary-color, #5568d3);
border-color: var(--primary-color, #5568d3);
background: var(--primary-color, #497671);
border-color: var(--primary-color, #497671);
}
}
.p-carousel-indicators {
.p-carousel-indicator.p-highlight button {
background: var(--primary-color, #5568d3);
background: var(--primary-color, #497671);
}
}
}
@@ -319,10 +321,10 @@
}
.cart-icon-btn {
background: var(--primary-color, #5568d3);
background: var(--primary-color, #497671);
&:hover {
background: var(--primary-hover, #4456b3);
background: var(--primary-hover, #3d635f);
}
}
}

View File

@@ -155,8 +155,8 @@
// Dexar header specific styles
:host-context(.dexar-header) {
.language-selector {
width: 52px;
height: 26px;
width: 56px;
height: 28px;
}
.language-button {

View File

@@ -3,4 +3,5 @@ export interface Category {
name: string;
parentID: number;
icon?: string;
wideBanner?: string;
}

View File

@@ -2,8 +2,9 @@
.cart-container.dexar {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
padding: 24px;
min-height: calc(100vh - 200px);
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
// Novo theme - Modern green design
@@ -16,38 +17,44 @@
}
.cart-container.dexar .cart-header {
margin-bottom: 24px;
margin-bottom: 28px;
display: flex;
justify-content: space-between;
align-items: center;
h1 {
font-size: 1.75rem;
font-weight: 600;
color: #1a1a1a;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 2rem;
font-weight: 700;
color: #1e3c38;
margin: 0;
}
.clear-cart-btn {
padding: 8px 16px;
background: #ef4444;
color: white;
border: none;
border-radius: 8px;
padding: 10px 20px;
background: transparent;
color: #697777;
border: 1px solid #d3dad9;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 0.9rem;
font-weight: 500;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 6px;
gap: 8px;
svg {
display: none;
display: block;
width: 16px;
height: 16px;
}
&:hover {
background: #dc2626;
background: #fef2f2;
border-color: #ef4444;
color: #ef4444;
transform: translateY(-1px);
}
@@ -114,41 +121,51 @@
justify-content: center;
padding: 80px 20px;
text-align: center;
background: #f5f3f9;
border-radius: 13px;
border: 1px solid #d3dad9;
.empty-icon {
margin-bottom: 24px;
margin-bottom: 28px;
svg {
width: 80px;
height: 80px;
width: 90px;
height: 90px;
opacity: 0.7;
}
}
h2 {
font-size: 1.5rem;
font-weight: 600;
color: #1a1a1a;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1.6rem;
font-weight: 700;
color: #1e3c38;
margin: 0 0 12px 0;
}
p {
font-size: 0.95rem;
color: #6b7280;
margin: 0 0 24px 0;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1rem;
color: #697777;
margin: 0 0 28px 0;
}
.shop-btn {
padding: 12px 24px;
background: #a855f7;
padding: 14px 32px;
background: #497671;
color: white;
text-decoration: none;
border-radius: 8px;
font-weight: 500;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 600;
font-size: 1rem;
transition: all 0.2s;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
&:hover {
background: #9333ea;
transform: translateY(-1px);
background: #3a5f5b;
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(73, 118, 113, 0.3);
}
}
}
@@ -256,26 +273,30 @@
// Dexar cart item
.cart-container.dexar .cart-item {
display: flex;
gap: 16px;
gap: 20px;
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 16px;
transition: all 0.3s ease;
border: 1px solid #d3dad9;
border-radius: 13px;
padding: 20px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
z-index: 1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
&:hover {
border-color: #d1d5db;
border-color: #a1b4b5;
box-shadow: 0 4px 12px rgba(73, 118, 113, 0.1);
transform: translateY(-1px);
}
.item-image {
flex-shrink: 0;
width: 80px;
height: 80px;
border-radius: 8px;
width: 100px;
height: 100px;
border-radius: 13px;
overflow: hidden;
background: #f3f4f6;
background: #f5f3f9;
border: 1px solid #d3dad9;
img {
width: 100%;
@@ -283,6 +304,12 @@
object-fit: contain;
background: white;
display: block;
padding: 6px;
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.05);
}
}
@@ -302,25 +329,26 @@
}
.item-name {
font-size: 1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1.05rem;
font-weight: 600;
color: #1a1a1a;
color: #1e3c38;
text-decoration: none;
transition: color 0.2s;
&:hover {
color: #a855f7;
color: #497671;
}
}
.remove-btn {
flex-shrink: 0;
padding: 4px;
padding: 6px;
background: transparent;
border: none;
color: #9ca3af;
color: #a1b4b5;
cursor: pointer;
border-radius: 6px;
border-radius: 8px;
transition: all 0.2s;
&:hover {
@@ -330,8 +358,9 @@
}
.item-description {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 0.875rem;
color: #6b7280;
color: #697777;
line-height: 1.5;
}
@@ -462,9 +491,10 @@
}
.current-price {
font-size: 1.1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1.15rem;
font-weight: 700;
color: #1a1a1a;
color: #497671;
}
}
@@ -473,16 +503,17 @@
display: flex;
align-items: center;
gap: 12px;
background: #f3f4f6;
border-radius: 20px;
padding: 4px 8px;
background: #f5f3f9;
border-radius: 13px;
padding: 4px 10px;
border: 1px solid #d3dad9;
.qty-btn {
width: 28px;
height: 28px;
width: 30px;
height: 30px;
border: none;
background: transparent;
color: #a855f7;
color: #497671;
cursor: pointer;
display: flex;
align-items: center;
@@ -491,7 +522,7 @@
transition: all 0.2s;
&:hover:not(:disabled) {
background: #a855f7;
background: #497671;
color: white;
}
@@ -502,10 +533,11 @@
}
.qty-value {
font-size: 0.95rem;
font-weight: 600;
color: #1a1a1a;
min-width: 20px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1rem;
font-weight: 700;
color: #1e3c38;
min-width: 24px;
text-align: center;
}
}
@@ -582,19 +614,21 @@
// Dexar Cart Summary
.cart-container.dexar .cart-summary {
position: sticky;
top: 20px;
background: white;
border: 1px solid #e5e7eb;
border-radius: 16px;
padding: 24px;
top: 90px;
background: #f5f3f9;
border: 1px solid #d3dad9;
border-radius: 13px;
padding: 28px;
display: flex;
flex-direction: column;
gap: 16px;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
.summary-header h3 {
font-size: 1.25rem;
font-weight: 600;
color: #1a1a1a;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1.4rem;
font-weight: 700;
color: #1e3c38;
margin: 0 0 16px 0;
}
@@ -602,8 +636,9 @@
display: flex;
justify-content: space-between;
align-items: center;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 0.95rem;
color: #6b7280;
color: #697777;
&.delivery {
display: flex;
@@ -611,35 +646,38 @@
&.total {
padding-top: 16px;
border-top: 1px solid #e5e7eb;
font-size: 1.1rem;
font-weight: 600;
color: #1a1a1a;
border-top: 1px solid #d3dad9;
font-size: 1.15rem;
font-weight: 700;
color: #1e3c38;
margin-top: 8px;
.total-price {
font-size: 1.25rem;
color: #1a1a1a;
font-size: 1.35rem;
color: #497671;
}
}
}
.checkout-btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #a855f7 0%, #9333ea 100%);
padding: 16px;
background: #497671;
color: white;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1.05rem;
font-weight: 700;
cursor: pointer;
transition: all 0.2s;
margin-top: 8px;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
&:hover:not(:disabled) {
transform: translateY(-1px);
box-shadow: 0 8px 16px rgba(168, 85, 247, 0.3);
background: #3a5f5b;
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(73, 118, 113, 0.3);
}
&:active {
@@ -790,7 +828,7 @@
line-height: 1.4;
a {
color: #a855f7;
color: var(--primary-color);
text-decoration: none;
&:hover {
@@ -804,13 +842,36 @@
// Dexar checkbox colors
.cart-container.dexar .terms-agreement .checkbox-container {
input[type="checkbox"]:checked ~ .checkmark {
background: #a855f7;
border-color: #a855f7;
background: #497671;
border-color: #497671;
&::after {
display: block;
}
}
.checkmark {
border: 2px solid #d3dad9;
border-radius: 4px;
}
.terms-text {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 0.85rem;
color: #697777;
line-height: 1.5;
a {
color: #497671;
text-decoration: none;
font-weight: 600;
&:hover {
text-decoration: underline;
color: #3a5f5b;
}
}
}
}
// Novo checkbox colors - green
@@ -861,13 +922,15 @@
.payment-modal {
background: white;
border-radius: 20px;
border-radius: 13px;
max-width: 500px;
width: 100%;
padding: 40px;
position: relative;
max-height: 90vh;
overflow-y: auto;
border: 1px solid #d3dad9;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
.close-modal-btn {
position: absolute;
@@ -980,8 +1043,8 @@
.spinner-small {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #a855f7;
border: 4px solid #d3dad9;
border-top: 4px solid #497671;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto;
@@ -1032,9 +1095,9 @@
left: 16px;
right: 16px;
height: 2px;
background: linear-gradient(90deg, transparent, #a855f7, transparent);
background: linear-gradient(90deg, transparent, #497671, transparent);
animation: scan 2s linear infinite;
box-shadow: 0 0 10px #a855f7;
box-shadow: 0 0 10px #497671;
}
@keyframes scan {
@@ -1084,7 +1147,7 @@
.pulse-dot {
width: 8px;
height: 8px;
background: #a855f7;
background: #497671;
border-radius: 50%;
animation: pulse 1.5s ease-in-out infinite;
}
@@ -1132,12 +1195,12 @@
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.25);
box-shadow: 0 4px 12px rgba(73, 118, 113, 0.25);
&:hover {
background: var(--primary-hover);
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.35);
box-shadow: 0 6px 16px rgba(73, 118, 113, 0.35);
}
&:active {
@@ -1198,8 +1261,8 @@
transition: all 0.2s;
&:focus {
border-color: #a855f7;
box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.1);
border-color: #497671;
box-shadow: 0 0 0 3px rgba(73, 118, 113, 0.1);
}
&.valid {
@@ -1225,12 +1288,13 @@
.submit-email-btn {
padding: 14px;
background: linear-gradient(135deg, #a855f7 0%, #9333ea 100%);
background: #497671;
color: white;
border: none;
border-radius: 8px;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 1rem;
font-weight: 600;
font-weight: 700;
cursor: pointer;
display: flex;
align-items: center;
@@ -1239,8 +1303,9 @@
transition: all 0.2s;
&:hover:not(:disabled) {
background: #3a5f5b;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(168, 85, 247, 0.3);
box-shadow: 0 4px 12px rgba(73, 118, 113, 0.3);
}
&:disabled {

View File

@@ -1,7 +1,8 @@
.category-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
padding: 24px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.error,
@@ -14,42 +15,54 @@
flex-direction: column;
align-items: center;
justify-content: center;
color: #697777;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.error button {
margin-top: 20px;
padding: 10px 24px;
background: var(--primary-color);
background: #497671;
color: white;
border: none;
border-radius: 6px;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
transition: all 0.2s ease;
&:hover {
background: var(--primary-hover);
background: #3a5f5b;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(73, 118, 113, 0.3);
}
}
.items-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 24px;
grid-template-columns: repeat(4, 1fr);
gap: 30px;
margin-bottom: 40px;
width: 100%;
}
.item-card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.2s, box-shadow 0.2s;
width: 100%;
display: flex;
flex-direction: column;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
transform: translateY(-4px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
.item-image {
box-shadow: 0 6px 8px 0 rgba(0, 0, 0, 0.2);
}
.item-details {
box-shadow: 0 6px 8px 0 rgba(0, 0, 0, 0.2);
}
}
}
@@ -64,27 +77,27 @@
.item-image {
position: relative;
width: 100%;
padding-top: 75%; // 4:3 aspect ratio
background: #f5f5f5;
aspect-ratio: 4 / 3;
border: 1px solid #d3dad9;
border-radius: 13px 13px 0 0;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
overflow: hidden;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
background: white;
padding: 12px;
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), filter 0.4s ease;
filter: drop-shadow(0 2px 6px rgba(0,0,0,0.06));
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.06) translateY(-2px);
filter: drop-shadow(0 12px 24px rgba(0,0,0,0.15)) brightness(1.03);
transform: scale(1.05);
}
}
@@ -98,33 +111,47 @@
border-radius: 20px;
font-weight: 600;
font-size: 0.9rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
z-index: 1;
}
.item-details {
padding: 16px;
width: 100%;
border: 1px solid #d3dad9;
border-top: none;
border-radius: 0 0 13px 13px;
padding: 12px 16px;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
background: #f5f3f9;
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
gap: 6px;
transition: background 0.3s ease;
}
.item-name {
font-size: 1.1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 600;
font-size: clamp(14px, 1.4vw, 18px);
color: #1e3c38;
margin: 0;
color: #333;
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
min-height: calc(2 * 1.3em);
}
.item-rating {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
color: #333;
gap: 6px;
font-size: 0.85rem;
color: #697777;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
.rating-stars {
color: #ffa502;
@@ -142,15 +169,17 @@
.original-price {
text-decoration: line-through;
color: #555;
font-size: 0.9rem;
color: #697777;
font-size: 0.85rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.discounted-price,
.current-price {
font-size: 1.3rem;
font-size: clamp(16px, 1.6vw, 22px);
font-weight: 700;
color: var(--primary-color);
color: #497671;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.item-stock {
@@ -162,16 +191,16 @@
.bar-segment {
width: 20px;
height: 6px;
background: #e0e0e0;
background: #d3dad9;
border-radius: 3px;
transition: background 0.2s;
&.filled.high {
background: #2ed573;
background: #497671;
}
&.filled.medium {
background: #ffa502;
background: #a1b4b5;
}
&.filled.low {
@@ -184,16 +213,19 @@
.add-to-cart-btn {
width: 100%;
padding: 12px;
background: var(--primary-color);
background: #497671;
color: white;
border: none;
font-size: 1rem;
border-radius: 0 0 13px 13px;
font-size: 0.95rem;
font-weight: 600;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
cursor: pointer;
transition: background 0.2s;
transition: all 0.2s ease;
margin-top: -1px;
&:hover {
background: var(--primary-hover);
background: #3a5f5b;
}
&:active {
@@ -209,8 +241,8 @@
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid var(--primary-color);
border: 4px solid #d3dad9;
border-top: 4px solid #497671;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 12px;
@@ -222,22 +254,65 @@
}
.no-more {
color: #555;
color: #697777;
padding: 40px 20px;
}
// Responsive
@media (max-width: 1200px) {
.items-grid {
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
}
@media (max-width: 992px) {
.items-grid {
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
}
@media (max-width: 768px) {
.items-grid {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}
.item-name {
font-size: 0.95rem;
font-size: clamp(12px, 3vw, 16px);
}
.discounted-price,
.current-price {
font-size: 1.1rem;
font-size: clamp(14px, 3.5vw, 18px);
}
.item-details {
padding: 10px 12px;
}
}
@media (max-width: 480px) {
.category-container {
padding: 12px;
}
.items-grid {
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.item-details {
padding: 8px 10px;
}
.item-card:hover {
transform: translateY(-2px);
}
.add-to-cart-btn {
padding: 10px;
font-size: 0.85rem;
}
}

View File

@@ -20,18 +20,18 @@
<div class="categories-grid">
@for (cat of subcategories(); track trackByCategoryId($index, cat)) {
<div class="category-card">
<a [routerLink]="['/category', cat.categoryID]" class="category-link">
<div class="category-media">
<a [routerLink]="['/category', cat.categoryID]" class="category-card">
<div class="category-image">
@if (cat.icon) {
<img [src]="cat.icon" [alt]="cat.name" loading="lazy" decoding="async" />
} @else {
<div class="category-fallback">{{ cat.name }}</div>
<div class="category-fallback">{{ cat.name.charAt(0) }}</div>
}
</div>
<h3>{{ cat.name }}</h3>
</a>
<div class="category-info">
<h3 class="category-name">{{ cat.name }}</h3>
</div>
</a>
}
</div>
}

View File

@@ -1,9 +1,9 @@
.subcategories-container {
max-width: 1100px;
max-width: 1200px;
margin: 0 auto;
padding: 24px;
// Loading состояние
// Loading state
.loading {
display: flex;
flex-direction: column;
@@ -15,20 +15,21 @@
.spinner {
width: 48px;
height: 48px;
border: 4px solid #f3f4f6;
border-top-color: #3b82f6;
border: 4px solid #d3dad9;
border-top-color: #497671;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
p {
color: #6b7280;
color: #697777;
font-size: 1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin: 0;
}
}
// Error состояние
// Error state
.error {
display: flex;
flex-direction: column;
@@ -41,25 +42,27 @@
p {
color: #dc2626;
font-size: 1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
text-align: center;
margin: 0;
}
button {
padding: 10px 24px;
background: #3b82f6;
background: #497671;
color: white;
border: none;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 500;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background: #2563eb;
background: #3a5f5b;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
box-shadow: 0 4px 12px rgba(73, 118, 113, 0.3);
}
&:active {
@@ -69,144 +72,134 @@
}
.sub-header {
margin-bottom: 24px;
position: relative;
padding-bottom: 12px;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 60px;
height: 3px;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
border-radius: 2px;
}
margin-bottom: 28px;
h2 {
font-size: 1.75rem;
color: #1f2937;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 2rem;
color: #1e3c38;
margin: 0;
font-weight: 600;
font-weight: 700;
letter-spacing: -0.02em;
}
}
.categories-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 20px;
grid-template-columns: repeat(4, 1fr);
gap: 30px;
width: 100%;
}
.category-card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
transition: all 0.3s ease;
animation: fadeInUp 0.5s ease backwards;
cursor: pointer;
// Анимация появления с задержкой для каждой карточки
@for $i from 1 through 20 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
text-decoration: none;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(0,0,0,0.12);
.category-image {
box-shadow: 0 6px 8px 0 rgba(0, 0, 0, 0.2);
}
.category-link {
display: flex;
flex-direction: column;
flex: 1;
text-decoration: none;
color: inherit;
position: relative;
min-height: 200px;
.category-info {
box-shadow: 0 6px 8px 0 rgba(0, 0, 0, 0.2);
}
}
}
.category-media {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
.category-image {
width: 100%;
aspect-ratio: 4 / 3;
border: 1px solid #d3dad9;
border-radius: 13px 13px 0 0;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: linear-gradient(135deg, #f6f7fb 0%, #e9ecf5 100%);
background: #f5f5f5;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&:hover .category-media {
&:hover img {
transform: scale(1.05);
}
.category-media img {
width: 100%;
height: 100%;
object-fit: contain;
background: white;
transition: opacity 0.3s ease;
}
.category-fallback {
text-align: center;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 5rem;
font-weight: 700;
color: #497671;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%);
}
.category-info {
width: 100%;
border: 1px solid #d3dad9;
border-top: none;
border-radius: 0 0 13px 13px;
padding: 12px 16px;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15);
background: #f5f3f9;
display: flex;
flex-direction: column;
justify-content: center;
gap: 2px;
transition: background 0.3s ease;
}
.category-name {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 600;
font-size: 1.1rem;
padding: 20px;
color: #6b7280;
}
h3 {
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
font-size: clamp(14px, 1.4vw, 18px);
color: #1e3c38;
margin: 0;
font-size: 0.95rem;
color: white;
padding: 12px 14px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.4) 70%, transparent);
z-index: 1;
font-weight: 500;
transition: all 0.3s ease;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
min-height: calc(2 * 1.3em);
}
&:hover h3 {
padding: 16px 14px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.5) 70%, transparent);
}
}
}
// Keyframes для анимаций
// Keyframes
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
// Responsive
@media (max-width: 1200px) {
padding: 24px;
.categories-grid {
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
}
@media (max-width: 992px) {
.categories-grid {
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
}
// Мобильная версия
@media (max-width: 768px) {
padding: 16px;
@@ -220,24 +213,14 @@
.categories-grid {
grid-template-columns: repeat(2, 1fr);
gap: 12px;
gap: 16px;
}
.category-card {
border-radius: 10px;
.category-link {
min-height: 140px;
h3 {
font-size: 0.85rem;
padding: 10px 8px;
}
}
.category-info {
padding: 10px 12px;
}
}
// Очень маленькие экраны
@media (max-width: 480px) {
padding: 12px;
@@ -250,52 +233,16 @@
}
.categories-grid {
gap: 10px;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.category-card {
.category-link {
min-height: 120px;
h3 {
font-size: 0.8rem;
padding: 8px 6px;
.category-info {
padding: 8px 10px;
}
.category-fallback {
font-size: 0.95rem;
padding: 12px;
}
}
}
}
// Большие экраны
@media (min-width: 1200px) {
padding: 32px;
.sub-header {
margin-bottom: 28px;
h2 {
font-size: 2rem;
}
}
.categories-grid {
gap: 24px;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.category-card {
.category-link {
min-height: 220px;
h3 {
font-size: 1rem;
padding: 14px 16px;
}
}
.category-card:hover {
transform: translateY(-2px);
}
}
}

View File

@@ -126,9 +126,13 @@
} @else {
<div class="dexar-categories-grid">
@for (category of getTopLevelCategories(); track category.categoryID) {
<a [routerLink]="['/category', category.categoryID]" class="dexar-category-card">
<a [routerLink]="['/category', category.categoryID]"
class="dexar-category-card"
[class.dexar-category-card--wide]="isWideCategory(category.categoryID)">
<div class="dexar-category-image">
@if (category.icon) {
@if (isWideCategory(category.categoryID) && category.wideBanner) {
<img [src]="category.wideBanner" [alt]="category.name" loading="lazy" decoding="async" />
} @else if (category.icon) {
<img [src]="category.icon" [alt]="category.name" loading="lazy" decoding="async" />
} @else {
<div class="dexar-category-fallback">{{ category.name.charAt(0) }}</div>

View File

@@ -741,10 +741,10 @@
}
.dexar-hero-content {
max-width: 660px;
max-width: 600px;
display: flex;
flex-direction: column;
gap: 18px;
gap: 12px;
animation: fadeInUp 0.8s ease-out;
}
@@ -762,7 +762,7 @@
.dexar-hero-title {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
font-size: 57px;
font-size: 42px;
color: #1e3c38;
line-height: 1.2;
margin: 0;
@@ -772,7 +772,7 @@
.dexar-hero-subtitle {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
font-size: 34px;
font-size: 24px;
color: #1e3c38;
line-height: 1.3;
margin: 0;
@@ -782,7 +782,7 @@
.dexar-hero-tagline {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
font-size: 34px;
font-size: 24px;
color: #1e3c38;
line-height: 1.3;
margin: 0;
@@ -791,8 +791,8 @@
.dexar-hero-actions {
display: flex;
gap: 20px;
margin-top: 20px;
gap: 16px;
margin-top: 12px;
animation: fadeInUp 0.8s ease-out 0.4s both;
}
@@ -800,14 +800,14 @@
display: flex;
align-items: center;
justify-content: center;
width: 337px;
height: 60px;
width: 280px;
height: 48px;
background: linear-gradient(360deg, #497671 0%, #a7ceca 100%);
border: 1px solid #d3dad9;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
font-size: 27px;
font-size: 20px;
color: #ffffff;
text-decoration: none;
letter-spacing: 1.08px;
@@ -831,14 +831,14 @@
align-items: center;
justify-content: center;
gap: 9px;
width: 264px;
height: 60px;
width: 220px;
height: 48px;
background: #f5f5f5;
border: 1px solid #d3dad9;
border-radius: 13px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-weight: 500;
font-size: 27px;
font-size: 20px;
color: #1e3c38;
letter-spacing: 1.08px;
cursor: pointer;
@@ -1037,6 +1037,7 @@
margin: 0;
line-height: 1.3;
display: -webkit-box;
line-clamp: 2;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
@@ -1053,10 +1054,23 @@
line-height: 1.2;
}
// Wide category card (spans 2 columns)
.dexar-category-card--wide {
grid-column: span 2;
.dexar-category-image {
aspect-ratio: 8 / 3;
img {
object-fit: cover;
}
}
}
// Responsive Design
@media (max-width: 1200px) {
.dexar-hero {
height: 500px;
height: 380px;
}
.dexar-hero-overlay {
@@ -1064,12 +1078,12 @@
}
.dexar-hero-title {
font-size: 48px;
font-size: 38px;
}
.dexar-hero-subtitle,
.dexar-hero-tagline {
font-size: 28px;
font-size: 22px;
}
.dexar-categories {
@@ -1084,7 +1098,7 @@
@media (max-width: 992px) {
.dexar-hero {
height: 450px;
height: 340px;
}
.dexar-hero-overlay {
@@ -1092,24 +1106,24 @@
}
.dexar-hero-title {
font-size: 42px;
font-size: 34px;
}
.dexar-hero-subtitle,
.dexar-hero-tagline {
font-size: 24px;
font-size: 20px;
}
.dexar-btn-primary {
width: 280px;
height: 54px;
font-size: 22px;
width: 240px;
height: 44px;
font-size: 18px;
}
.dexar-btn-secondary {
width: 220px;
height: 54px;
font-size: 22px;
width: 200px;
height: 44px;
font-size: 18px;
}
.dexar-categories {
@@ -1124,7 +1138,7 @@
@media (max-width: 768px) {
.dexar-hero {
height: 400px;
height: 320px;
background-position: right center;
}
@@ -1138,26 +1152,26 @@
}
.dexar-hero-title {
font-size: 36px;
font-size: 28px;
}
.dexar-hero-subtitle,
.dexar-hero-tagline {
font-size: 20px;
font-size: 17px;
}
.dexar-hero-actions {
flex-direction: column;
gap: 16px;
gap: 12px;
width: 100%;
}
.dexar-btn-primary,
.dexar-btn-secondary {
width: 100%;
max-width: 320px;
height: 50px;
font-size: 20px;
max-width: 280px;
height: 42px;
font-size: 17px;
}
.dexar-categories {
@@ -1182,26 +1196,26 @@
@media (max-width: 480px) {
.dexar-hero {
height: 350px;
height: 280px;
}
.dexar-hero-title {
font-size: 28px;
font-size: 24px;
}
.dexar-hero-subtitle,
.dexar-hero-tagline {
font-size: 18px;
font-size: 15px;
}
.dexar-hero-actions {
gap: 12px;
gap: 10px;
}
.dexar-btn-primary,
.dexar-btn-secondary {
height: 46px;
font-size: 18px;
height: 40px;
font-size: 16px;
}
.dexar-categories {

View File

@@ -20,6 +20,7 @@ export class HomeComponent implements OnInit {
isnovo = environment.theme === 'novo';
categories = signal<Category[]>([]);
itemCounts = signal<Map<number, number>>(new Map());
wideCategories = signal<Set<number>>(new Set());
loading = signal(true);
error = signal<string | null>(null);
@@ -55,6 +56,7 @@ export class HomeComponent implements OnInit {
this.categories.set(categories);
this.loading.set(false);
this.loadItemCounts();
this.detectWideImages(categories);
},
error: (err) => {
this.error.set('Failed to load categories');
@@ -97,6 +99,30 @@ export class HomeComponent implements OnInit {
return this.subcategoriesCache().get(parentID) || [];
}
isWideCategory(categoryID: number): boolean {
return this.wideCategories().has(categoryID);
}
private detectWideImages(categories: Category[]): void {
const topLevel = categories.filter(c => c.parentID === 0);
topLevel.forEach(cat => {
const src = cat.wideBanner || null;
if (!src) return;
const img = new Image();
img.onload = () => {
const ratio = img.naturalWidth / img.naturalHeight;
if (ratio > 2) {
this.wideCategories.update(set => {
const next = new Set(set);
next.add(cat.categoryID);
return next;
});
}
};
img.src = src;
});
}
navigateToSearch(): void {
this.router.navigate(['/search']);
}

View File

@@ -192,201 +192,240 @@
}
</div>
} @else {
<!-- DEXAR VERSION - Original -->
<div class="item-detail-container">
<!-- DEXAR VERSION - Redesigned 2026 -->
<div class="dx-item-container">
@if (loading()) {
<div class="loading">
<div class="spinner"></div>
<div class="dx-loading">
<div class="dx-spinner"></div>
<p>Загрузка товара...</p>
</div>
}
@if (error()) {
<div class="error">
<div class="dx-error">
<p>{{ error() }}</p>
<a routerLink="/" class="back-link">Вернуться на главную</a>
<a routerLink="/" class="dx-back-link">Вернуться на главную</a>
</div>
}
@if (item() && !loading()) {
<div class="item-content">
<div class="item-gallery">
<div class="dx-item-content">
<!-- Gallery: thumbnails left + main photo -->
<div class="dx-gallery">
@if (item()?.photos && item()!.photos!.length > 0) {
<div class="main-photo">
@if (item()!.photos![selectedPhotoIndex()]?.video) {
<video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video>
} @else {
<img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="item()!.name" fetchpriority="high" decoding="async" width="600" height="600" />
}
</div>
<div class="photo-thumbnails">
<div class="dx-thumbnails">
@for (photo of item()!.photos!; track $index) {
<div
class="thumbnail"
class="dx-thumb"
[class.active]="selectedPhotoIndex() === $index"
(click)="selectPhoto($index)">
@if (photo.video) {
<div class="video-indicator"></div>
<div class="dx-video-badge"></div>
}
<img [src]="photo.url" [alt]="'Photo ' + ($index + 1)" loading="lazy" decoding="async" />
<img [src]="photo.url" [alt]="'Фото ' + ($index + 1)" loading="lazy" decoding="async" />
</div>
}
</div>
}
<div class="dx-main-photo">
@if (item()?.photos && item()!.photos!.length > 0) {
@if (item()!.photos![selectedPhotoIndex()]?.video) {
<video [src]="item()!.photos![selectedPhotoIndex()].url" controls></video>
} @else {
<div class="main-photo">
<div class="no-image">📦 Нет изображения</div>
<img [src]="item()!.photos![selectedPhotoIndex()].url" [alt]="item()!.name" fetchpriority="high" decoding="async" />
}
} @else {
<div class="dx-no-image">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#a1b4b5" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<path d="M21 15l-5-5L5 21"></path>
</svg>
<span>Нет изображения</span>
</div>
}
</div>
<div class="item-info">
<h1>{{ item()!.name }}</h1>
<div class="rating-section">
<span class="rating">{{ getRatingStars(item()!.rating) }} {{ item()!.rating }}</span>
<span class="reviews-count">({{ item()!.callbacks?.length || 0 }} отзывов)</span>
</div>
<div class="price-section">
<!-- Item Info -->
<div class="dx-info">
<h1 class="dx-title">{{ item()!.name }}</h1>
<div class="dx-rating">
<div class="dx-stars">
@for (star of [1, 2, 3, 4, 5]; track star) {
<svg width="18" height="18" viewBox="0 0 24 24" [attr.fill]="star <= item()!.rating ? '#497671' : 'none'" [attr.stroke]="star <= item()!.rating ? '#497671' : '#a1b4b5'" stroke-width="2">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
}
</div>
<span class="dx-rating-value">{{ item()!.rating }}</span>
<span class="dx-rating-count">({{ item()!.callbacks?.length || 0 }} отзывов)</span>
</div>
<div class="dx-price-block">
@if (item()!.discount > 0) {
<div class="discount-info">
<span class="original-price">{{ item()!.price }} {{ item()!.currency }}</span>
<span class="discount-badge">-{{ item()!.discount }}%</span>
<div class="dx-price-row">
<span class="dx-old-price">{{ item()!.price }} {{ item()!.currency }}</span>
<span class="dx-discount-tag">-{{ item()!.discount }}%</span>
</div>
<div class="current-price">{{ getDiscountedPrice() | number:'1.2-2' }} {{ item()!.currency }}</div>
} @else {
<div class="current-price">{{ item()!.price }} {{ item()!.currency }}</div>
}
</div>
<div class="stock-info">
<div class="stock-bar">
<span class="bar-segment" [class.filled]="item()!.remainings === 'high' || item()!.remainings === 'medium' || item()!.remainings === 'low'" [class.high]="item()!.remainings === 'high'" [class.medium]="item()!.remainings === 'medium'" [class.low]="item()!.remainings === 'low'"></span>
<span class="bar-segment" [class.filled]="item()!.remainings === 'high' || item()!.remainings === 'medium'" [class.high]="item()!.remainings === 'high'" [class.medium]="item()!.remainings === 'medium'"></span>
<span class="bar-segment" [class.filled]="item()!.remainings === 'high'" [class.high]="item()!.remainings === 'high'"></span>
<div class="dx-current-price">
{{ item()!.discount > 0 ? (getDiscountedPrice() | number:'1.2-2') : item()!.price }} {{ item()!.currency }}
</div>
</div>
<button class="add-to-cart-btn" (click)="addToCart()">
<div class="dx-stock">
<span class="dx-stock-label">Наличие:</span>
<span class="dx-stock-status"
[class.high]="item()!.remainings === 'high'"
[class.medium]="item()!.remainings === 'medium'"
[class.low]="item()!.remainings === 'low'">
<span class="dx-stock-dot"></span>
{{ item()!.remainings === 'high' ? 'В наличии' : item()!.remainings === 'medium' ? 'Заканчивается' : 'Последние штуки' }}
</span>
</div>
<button class="dx-add-cart" (click)="addToCart()">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
Добавить в корзину
</button>
<div class="description-section">
<div class="dx-description">
<h2>Описание</h2>
<div class="description" [innerHTML]="getSafeHtml(item()!.description)"></div>
<div class="dx-description-text" [innerHTML]="getSafeHtml(item()!.description)"></div>
</div>
</div>
</div>
<div class="reviews-section">
<!-- Reviews Section -->
<div class="dx-reviews-section">
<h2>Отзывы ({{ item()!.callbacks?.length || 0 }})</h2>
<!-- Review Submission Form -->
<div class="review-form">
<div class="dx-review-form">
<h3>Оставить отзыв</h3>
<div class="rating-input">
<div class="dx-rating-input">
<label>Оценка:</label>
<div class="star-selector">
<div class="dx-star-selector">
@for (star of [1, 2, 3, 4, 5]; track star) {
<span
class="star"
class="dx-star-pick"
[class.selected]="newReview.rating >= star"
(click)="setRating(star)">
</span>
}
</div>
</div>
<textarea
[(ngModel)]="newReview.comment"
placeholder="Напишите свой отзыв..."
rows="4">
placeholder="Поделитесь впечатлениями о товаре..."
rows="4"
class="dx-textarea">
</textarea>
<div class="form-actions">
<label class="anonymous-toggle">
<div class="dx-form-actions">
<label class="dx-anon-toggle">
<input type="checkbox" [(ngModel)]="newReview.anonymous">
Анонимно
<span>Анонимно</span>
</label>
@if (!newReview.anonymous && getUserDisplayName()) {
<span class="username-preview">Опубликуется как: {{ getUserDisplayName() }}</span>
<span class="dx-user-preview">{{ getUserDisplayName() }}</span>
}
<button
class="submit-review-btn"
class="dx-submit-btn"
(click)="submitReview()"
[disabled]="!newReview.rating || !newReview.comment.trim() || reviewSubmitStatus() === 'loading'"
[class.submitting]="reviewSubmitStatus() === 'loading'">
@if (reviewSubmitStatus() === 'loading') {
<span class="spinner-small"></span>
<span class="dx-spinner-sm"></span>
Отправка...
} @else {
Отправить отзыв
Отправить
}
</button>
</div>
@if (reviewSubmitStatus() === 'success') {
<div class="status-message success">
<span class="icon"></span>
<div class="dx-status success">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 6L9 17l-5-5"/></svg>
Спасибо за ваш отзыв!
</div>
}
@if (reviewSubmitStatus() === 'error') {
<div class="status-message error">
<span class="icon"></span>
<div class="dx-status error">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M18 6L6 18M6 6l12 12"/></svg>
Ошибка отправки. Попробуйте позже.
</div>
}
</div>
<div class="reviews-list">
<div class="dx-reviews-list">
@if (item()?.callbacks && item()!.callbacks!.length > 0) {
@for (callback of item()!.callbacks; track $index) {
<div class="review-card">
<div class="review-header">
<span class="review-author">{{ callback.userID || 'Аноним' }}</span>
@if (callback.rating) {
<div class="review-rating">{{ getRatingStars(callback.rating) }}</div>
}
<div class="dx-review-card">
<div class="dx-review-header">
<div class="dx-reviewer">
<span class="dx-reviewer-name">{{ callback.userID || 'Аноним' }}</span>
@if (callback.timestamp) {
<span class="review-date">{{ formatDate(callback.timestamp) }}</span>
<span class="dx-review-date">{{ formatDate(callback.timestamp) }}</span>
}
</div>
@if (callback.rating) {
<div class="dx-review-stars">
@for (star of [1, 2, 3, 4, 5]; track star) {
<svg width="14" height="14" viewBox="0 0 24 24" [attr.fill]="star <= callback.rating ? '#497671' : 'none'" [attr.stroke]="star <= callback.rating ? '#497671' : '#d3dad9'" stroke-width="2">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
}
</div>
}
</div>
@if (callback.content) {
<p class="review-text">{{ callback.content }}</p>
<p class="dx-review-text">{{ callback.content }}</p>
}
</div>
}
} @else {
<p class="no-reviews">Пока нет отзывов</p>
<p class="dx-no-reviews">Пока нет отзывов. Станьте первым!</p>
}
</div>
</div>
<div class="questions-section">
<h2>Вопросы и ответы ({{ item()!.questions?.length || 0 }})</h2>
<div class="questions-list">
@if (item()?.questions && item()!.questions!.length > 0) {
@for (question of item()!.questions; track $index) {
<div class="question-card">
<div class="question-text">
<strong>В:</strong> {{ question.question }}
<!-- Q&A Section -->
@if (item()!.questions && item()!.questions!.length > 0) {
<div class="dx-qa-section">
<h2>Вопросы и ответы ({{ item()!.questions!.length }})</h2>
<div class="dx-qa-list">
@for (question of item()!.questions!; track $index) {
<div class="dx-qa-card">
<div class="dx-question">
<span class="dx-qa-label q">В</span>
<span>{{ question.question }}</span>
</div>
<div class="answer-text">
<strong>О:</strong> {{ question.answer }}
<div class="dx-answer">
<span class="dx-qa-label a">О</span>
<span>{{ question.answer }}</span>
</div>
<div class="question-votes">
<span class="vote-up">👍 {{ question.upvotes }}</span>
<span class="vote-down">👎 {{ question.downvotes }}</span>
<div class="dx-qa-votes">
<button class="dx-vote up">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3H14z"/><path d="M7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"/></svg>
{{ question.upvotes }}
</button>
<button class="dx-vote down">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3H10z"/><path d="M17 2h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"/></svg>
{{ question.downvotes }}
</button>
</div>
</div>
}
} @else {
<p class="no-questions">Пока нет вопросов</p>
</div>
</div>
}
</div>
</div>
}
</div>
}

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,12 @@
class="search-input"
autofocus
/>
<span class="search-icon">🔍</span>
<span class="search-icon">
<svg width="22" height="22" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#697777" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#697777" />
</svg>
</span>
</div>
</div>
@@ -36,7 +41,12 @@
@if (!loading() && searchQuery && items().length === 0 && !error()) {
<div class="no-results">
<div class="no-results-icon">🔍</div>
<div class="no-results-icon">
<svg width="48" height="48" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZZ2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#a1b4b5" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2929 18.2929C18.6834 17.9024 19.3166 17.9024 19.7071 18.2929L25.7071 24.2929C26.0976 24.6834 26.0976 25.3166 25.7071 25.7071C25.3166 26.0976 24.6834 26.0976 24.2929 25.7071L18.2929 19.7071C17.9024 19.3166 17.9024 18.6834 18.2929 18.2929Z" fill="#a1b4b5" />
</svg>
</div>
<h2>Ничего не найдено</h2>
<p>По запросу "{{ searchQuery }}" товары не найдены</p>
<p class="hint">Попробуйте изменить запрос или используйте другие ключевые слова</p>

View File

@@ -2,6 +2,7 @@
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.search-header {
@@ -10,7 +11,7 @@
h1 {
font-size: 2rem;
margin-bottom: 20px;
color: #333;
color: #1e3c38;
text-align: center;
}
}
@@ -24,13 +25,15 @@
width: 100%;
padding: 16px 50px 16px 20px;
font-size: 1.1rem;
border: 2px solid #ddd;
border-radius: 50px;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
border: 2px solid #d3dad9;
border-radius: 13px;
outline: none;
transition: border-color 0.2s;
&:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(73, 118, 113, 0.1);
}
}
@@ -39,7 +42,8 @@
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 1.5rem;
display: flex;
align-items: center;
pointer-events: none;
}
}
@@ -47,7 +51,7 @@
.results-count {
text-align: center;
margin-bottom: 24px;
color: #333;
color: #1e3c38;
font-size: 1.1rem;
}
@@ -56,30 +60,31 @@
.loading-initial {
text-align: center;
padding: 60px 20px;
color: #555;
color: #697777;
}
.no-results {
.no-results-icon {
font-size: 4rem;
margin-bottom: 20px;
opacity: 0.3;
opacity: 0.5;
display: flex;
justify-content: center;
}
h2 {
font-size: 1.5rem;
color: #333;
color: #1e3c38;
margin-bottom: 12px;
}
p {
margin: 8px 0;
color: #666;
color: #697777;
}
.hint {
font-size: 0.9rem;
color: #999;
color: #a1b4b5;
margin-top: 16px;
}
}
@@ -94,9 +99,10 @@
background: var(--primary-color);
color: white;
border: none;
border-radius: 6px;
border-radius: 13px;
cursor: pointer;
font-size: 1rem;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
&:hover {
background: var(--primary-hover);
@@ -113,8 +119,9 @@
.item-card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border-radius: 13px;
border: 1px solid #d3dad9;
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.08);
overflow: hidden;
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
@@ -122,7 +129,7 @@
&:hover {
transform: translateY(-4px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
}
@@ -140,7 +147,7 @@
padding-top: 75%;
background: #f5f5f5;
overflow: hidden;
border-radius: 12px;
border-radius: 13px;
img {
position: absolute;
@@ -165,7 +172,7 @@
position: absolute;
top: 12px;
right: 12px;
background: #ff4757;
background: #ef4444;
color: white;
padding: 6px 12px;
border-radius: 20px;
@@ -184,7 +191,7 @@
.item-name {
font-size: 1.1rem;
margin: 0;
color: #333;
color: #1e3c38;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
@@ -197,10 +204,10 @@
align-items: center;
gap: 8px;
font-size: 0.9rem;
color: #333;
color: #1e3c38;
.rating-stars {
color: #ffa502;
color: #497671;
font-weight: 600;
}
}
@@ -215,7 +222,7 @@
.original-price {
text-decoration: line-through;
color: #555;
color: #697777;
font-size: 0.9rem;
}
@@ -235,7 +242,7 @@
.bar-segment {
width: 20px;
height: 6px;
background: #e0e0e0;
background: #d3dad9;
border-radius: 3px;
transition: background 0.2s;
@@ -248,7 +255,7 @@
}
&.filled.low {
background: #ff4757;
background: #ef4444;
}
}
}
@@ -260,8 +267,10 @@
background: var(--primary-color);
color: white;
border: none;
border-radius: 0 0 13px 13px;
font-size: 1rem;
font-weight: 600;
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
cursor: pointer;
transition: background 0.2s;
@@ -295,7 +304,7 @@
}
.no-more {
color: #555;
color: #697777;
padding: 40px 20px;
text-align: center;
}

View File

@@ -14,39 +14,40 @@
/* Default CSS Variables - will be overridden by theme files */
:root {
--primary-color: #667eea;
--primary-hover: #5568d3;
--secondary-color: #764ba2;
--secondary-hover: #653a8e;
--accent-color: #f093fb;
--accent-hover: #e07ff0;
--primary-color: #497671;
--primary-hover: #3d635f;
--secondary-color: #a1b4b5;
--secondary-hover: #8da3a4;
--accent-color: #a7ceca;
--accent-hover: #91b9b5;
--gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--gradient-secondary: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
--gradient-hero: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--gradient-primary: linear-gradient(360deg, #497671 0%, #a7ceca 100%);
--gradient-secondary: linear-gradient(135deg, #a1b4b5 0%, #677b78 100%);
--gradient-hero: linear-gradient(360deg, #497671 0%, #a7ceca 100%);
--text-primary: #333333;
--text-secondary: #666666;
--text-light: #999999;
--text-primary: #1e3c38;
--text-secondary: #667a77;
--text-light: #828e8d;
--bg-primary: #ffffff;
--bg-secondary: #f6f7fb;
--bg-tertiary: #e9ecf5;
--bg-secondary: #f5f5f5;
--bg-tertiary: #f0f0f0;
--success-color: #10b981;
--warning-color: #f59e0b;
--error-color: #ef4444;
--info-color: #3b82f6;
--border-color: #e5e7eb;
--border-color: #d3dad9;
--border-dark: #677b78;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.1);
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 12px 40px rgba(102, 126, 234, 0.25);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
--shadow-lg: 0 12px 32px rgba(73, 118, 113, 0.2);
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-lg: 13px;
--radius-xl: 22px;
}
* {
@@ -66,7 +67,7 @@ body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: linear-gradient(to bottom, #f8f9fa 0%, #e9ecef 100%);
background: #f5f5f5;
min-height: 100vh;
overflow-x: hidden;
}

View File

@@ -16,8 +16,8 @@
--text-light: #828e8d;
--bg-primary: #ffffff;
--bg-secondary: rgba(255, 255, 255, 0.74);
--bg-tertiary: #f5f5f5;
--bg-secondary: #f5f5f5;
--bg-tertiary: #f0f0f0;
--bg-header: rgba(117, 121, 124, 0.1);
--success-color: #10b981;
@@ -36,3 +36,7 @@
--radius-lg: 13px;
--radius-xl: 22px;
}
body {
font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}