diff --git a/src/app/features/website/catalog/containers/catalog-container.component.html b/src/app/features/website/catalog/containers/catalog-container.component.html index e427a12..8b1ec44 100644 --- a/src/app/features/website/catalog/containers/catalog-container.component.html +++ b/src/app/features/website/catalog/containers/catalog-container.component.html @@ -39,12 +39,12 @@ @if (loading()) { -
+
@for (slot of skeletonSlots; track $index) {
-
-
-
+ + +
}
@@ -52,9 +52,12 @@ @if (error()) {
-

{{ 'catalog.errorTitle' | translate }}

-

{{ error()! | translate }}

- + + +
+ {{ 'catalog.retry' | translate }} +
+
} @@ -86,8 +89,7 @@ } @else {
-

{{ 'catalog.emptyTitle' | translate }}

-

{{ 'catalog.emptyCategories' | translate }}

+
}
@@ -152,8 +154,7 @@ @if (offlineState()) {
-

{{ 'catalog.offlineTitle' | translate }}

-

{{ 'catalog.offlineMessage' | translate }}

+
} @else if (loadingProducts()) { @if (loading()) { -
-
-

{{ 'productDetails.loading' | translate }}

+
+
+ +
+ + + + +
+
+ {{ 'productDetails.loading' | translate }}
} @if (error()) { } @if (missing() && !loading() && !error()) {
-

{{ 'productDetails.missingTitle' | translate }}

-

{{ 'productDetails.missingDescription' | translate }}

- {{ 'productDetails.backToCatalog' | translate }} + +
+ {{ 'productDetails.backToCatalog' | translate }} +
+
} diff --git a/src/app/features/website/product/containers/product-details-container.component.scss b/src/app/features/website/product/containers/product-details-container.component.scss index e05a279..f6056ac 100644 --- a/src/app/features/website/product/containers/product-details-container.component.scss +++ b/src/app/features/website/product/containers/product-details-container.component.scss @@ -35,58 +35,51 @@ gap: 16px; } -.product-details-loading, +.product-details-loading { + min-height: 420px; +} + .product-details-message { min-height: 420px; display: flex; flex-direction: column; align-items: center; justify-content: center; - gap: 14px; - text-align: center; - color: #697777; - - h1 { - margin: 0; - color: #1e3c38; - } - - p { - margin: 0; - max-width: 420px; - } - - button, - a { - min-height: 42px; - padding: 0 22px; - border: 0; - border-radius: var(--radius-lg, 13px); - background: #497671; - color: #fff; - text-decoration: none; - display: inline-flex; - align-items: center; - font-weight: 800; - cursor: pointer; - } } .product-details-message.error { - color: #991b1b; + ::ng-deep .app-empty-state__title { + color: var(--error-color); + } } -.product-details-spinner { - width: 46px; - height: 46px; - border: 4px solid #d3dad9; - border-top-color: #497671; - border-radius: 50%; - animation: spin 0.8s linear infinite; +.product-details-loading-layout { + display: grid; + grid-template-columns: minmax(280px, 0.9fr) minmax(340px, 1fr); + gap: 28px; + align-items: start; } -@keyframes spin { - to { transform: rotate(360deg); } +.product-details-loading-gallery { + aspect-ratio: 1 / 1; +} + +.product-details-loading-main { + display: flex; + flex-direction: column; + gap: 16px; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } @media (max-width: 860px) { @@ -95,7 +88,8 @@ gap: 24px; } - .product-details-layout { + .product-details-layout, + .product-details-loading-layout { grid-template-columns: 1fr; gap: 18px; } diff --git a/src/app/features/website/product/containers/product-details-container.component.ts b/src/app/features/website/product/containers/product-details-container.component.ts index 5c4a4a5..7460c77 100644 --- a/src/app/features/website/product/containers/product-details-container.component.ts +++ b/src/app/features/website/product/containers/product-details-container.component.ts @@ -28,6 +28,9 @@ import { ProductVariantSelectorComponent, VariantOptionGroup } from '../componen import { ProductTabItem, ProductTabKey, ProductTabsComponent } from '../engagement/components/product-tabs/product-tabs.component'; import { QuestionListComponent } from '../engagement/components/question-list/question-list.component'; import { ReviewListComponent } from '../engagement/components/review-list/review-list.component'; +import { EmptyStateComponent } from '../../../../shared/ui/empty-state/empty-state.component'; +import { SkeletonComponent } from '../../../../shared/ui/skeleton/skeleton.component'; +import { ButtonComponent } from '../../../../shared/ui/button/button.component'; @Component({ selector: 'app-product-details-container', @@ -48,6 +51,9 @@ import { ReviewListComponent } from '../engagement/components/review-list/review ReviewListComponent, QuestionListComponent, RelatedProductsComponent, + EmptyStateComponent, + SkeletonComponent, + ButtonComponent, ], templateUrl: './product-details-container.component.html', styleUrls: ['./product-details-container.component.scss'], diff --git a/src/app/features/website/user-experience/compare/containers/compare-page.component.html b/src/app/features/website/user-experience/compare/containers/compare-page.component.html index 792a472..8af8411 100644 --- a/src/app/features/website/user-experience/compare/containers/compare-page.component.html +++ b/src/app/features/website/user-experience/compare/containers/compare-page.component.html @@ -6,7 +6,7 @@ @if (hasItems()) { - + {{ 'ux.clearCompare' | translate }} } @@ -38,9 +38,11 @@ [highlightDifferences]="highlightDifferences()" /> } @else {
-

{{ 'ux.compareEmptyTitle' | translate }}

-

{{ 'ux.compareEmptyDescription' | translate }}

- {{ 'ux.goToCatalog' | translate }} + +
+ {{ 'ux.goToCatalog' | translate }} +
+
} diff --git a/src/app/features/website/user-experience/compare/containers/compare-page.component.scss b/src/app/features/website/user-experience/compare/containers/compare-page.component.scss index 3c5ab98..60c6937 100644 --- a/src/app/features/website/user-experience/compare/containers/compare-page.component.scss +++ b/src/app/features/website/user-experience/compare/containers/compare-page.component.scss @@ -67,18 +67,7 @@ .compare-empty { min-height: 220px; - display: grid; - place-content: center; - gap: 8px; - text-align: center; - padding: 24px; -} - -.compare-empty h2, -.compare-empty p { - margin: 0; -} - -.compare-empty p { - color: var(--text-secondary); + display: flex; + align-items: center; + justify-content: center; } diff --git a/src/app/features/website/user-experience/compare/containers/compare-page.component.ts b/src/app/features/website/user-experience/compare/containers/compare-page.component.ts index 56e4baa..f21f025 100644 --- a/src/app/features/website/user-experience/compare/containers/compare-page.component.ts +++ b/src/app/features/website/user-experience/compare/containers/compare-page.component.ts @@ -7,11 +7,13 @@ import { TranslatePipe } from '../../../../../i18n/translate.pipe'; import { LangRoutePipe } from '../../../../../pipes/lang-route.pipe'; import { DEFAULT_USER_EXPERIENCE_CONFIG } from '../../../../../shared/models/config'; import { CompareTableComponent } from '../components/compare-table.component'; +import { EmptyStateComponent } from '../../../../../shared/ui/empty-state/empty-state.component'; +import { ButtonComponent } from '../../../../../shared/ui/button/button.component'; @Component({ selector: 'app-compare-page', standalone: true, - imports: [RouterLink, TranslatePipe, LangRoutePipe, CompareTableComponent], + imports: [RouterLink, TranslatePipe, LangRoutePipe, CompareTableComponent, EmptyStateComponent, ButtonComponent], templateUrl: './compare-page.component.html', styleUrls: ['./compare-page.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush diff --git a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.html b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.html index 4687661..ff8b08a 100644 --- a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.html +++ b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.html @@ -5,7 +5,7 @@

{{ favorites().length }} {{ 'ux.items' | translate }}

@if (hasItems()) { - + {{ 'ux.clearWishlist' | translate }} } @@ -27,9 +27,11 @@
} @else {
-

{{ 'ux.wishlistEmptyTitle' | translate }}

-

{{ 'ux.wishlistEmptyDescription' | translate }}

- {{ 'ux.goToCatalog' | translate }} + +
+ {{ 'ux.goToCatalog' | translate }} +
+
} diff --git a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.scss b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.scss index 3d0371e..86ac276 100644 --- a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.scss +++ b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.scss @@ -30,18 +30,7 @@ .wishlist-empty { min-height: 220px; - display: grid; - place-content: center; - gap: 8px; - text-align: center; - padding: 24px; -} - -.wishlist-empty h2, -.wishlist-empty p { - margin: 0; -} - -.wishlist-empty p { - color: var(--text-secondary); + display: flex; + align-items: center; + justify-content: center; } diff --git a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.ts b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.ts index 61695ef..aa4642a 100644 --- a/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.ts +++ b/src/app/features/website/user-experience/wishlist/containers/wishlist-page.component.ts @@ -7,11 +7,13 @@ import { TranslateService } from '../../../../../i18n/translate.service'; import { LangRoutePipe } from '../../../../../pipes/lang-route.pipe'; import { CartService } from '../../../../../services'; import { UserNotificationService } from '../../services/user-notification.service'; +import { EmptyStateComponent } from '../../../../../shared/ui/empty-state/empty-state.component'; +import { ButtonComponent } from '../../../../../shared/ui/button/button.component'; @Component({ selector: 'app-wishlist-page', standalone: true, - imports: [RouterLink, ProductCardComponent, TranslatePipe, LangRoutePipe], + imports: [RouterLink, ProductCardComponent, TranslatePipe, LangRoutePipe, EmptyStateComponent, ButtonComponent], templateUrl: './wishlist-page.component.html', styleUrls: ['./wishlist-page.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush diff --git a/src/app/pages/cart/cart.component.html b/src/app/pages/cart/cart.component.html index 60ca347..f51b982 100644 --- a/src/app/pages/cart/cart.component.html +++ b/src/app/pages/cart/cart.component.html @@ -11,12 +11,12 @@ @if (itemCount() === 0) {
-
- -
-

{{ 'cart.empty' | translate }}

-

{{ 'cart.emptyDesc' | translate }}

- {{ 'cart.goShopping' | translate }} + + +
+ {{ 'cart.goShopping' | translate }} +
+
} diff --git a/src/app/pages/cart/cart.component.scss b/src/app/pages/cart/cart.component.scss index abb8c2b..cfaefb1 100644 --- a/src/app/pages/cart/cart.component.scss +++ b/src/app/pages/cart/cart.component.scss @@ -7,15 +7,6 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } -// alt theme - Modern green design -.cart-container.alt { - max-width: 1200px; - margin: 0 auto; - padding: 24px; - min-height: calc(100vh - 200px); - background: linear-gradient(to bottom, rgba(16, 185, 129, 0.02) 0%, transparent 300px); -} - .cart-container.platform .cart-header { margin-bottom: 28px; display: flex; @@ -26,15 +17,15 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-4xl, 2rem); font-weight: var(--font-weight-bold, 700); - color: #1e3c38; + color: var(--text-primary); margin: 0; } .clear-cart-btn { padding: 10px 20px; background: transparent; - color: #697777; - border: 1px solid #d3dad9; + color: var(--text-secondary); + border: 1px solid var(--border-color); border-radius: var(--radius-lg, 13px); font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-base, 0.875rem); @@ -64,163 +55,11 @@ } } -.cart-container.alt .cart-header { - margin-bottom: 32px; +.empty-cart { + min-height: 320px; display: flex; - justify-content: space-between; - align-items: center; - - h1 { - font-size: var(--font-size-4xl, 2rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - margin: 0; - background: linear-gradient(135deg, #059669 0%, #10b981 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - } - - .clear-cart-btn { - padding: 10px 18px; - background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); - color: white; - border: none; - border-radius: var(--radius-md, 12px); - font-size: var(--font-size-base, 0.875rem); - font-weight: var(--font-weight-semibold, 600); - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - display: flex; - align-items: center; - gap: 8px; - box-shadow: 0 4px 12px rgba(239, 68, 68, 0.25); - - svg { - display: block; - width: 18px; - height: 18px; - } - - &:hover { - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(239, 68, 68, 0.35); - } - - &:active { - transform: translateY(0); - } - } -} - -// Empty cart - platform -.cart-container.platform .empty-cart { - display: flex; - flex-direction: column; align-items: center; justify-content: center; - padding: 80px 20px; - text-align: center; - background: #f5f3f9; - border-radius: var(--radius-lg, 13px); - border: 1px solid #d3dad9; - - .empty-icon { - margin-bottom: 28px; - - svg { - width: 90px; - height: 90px; - opacity: 0.7; - } - } - - h2 { - font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - font-size: 1.6rem; - font-weight: var(--font-weight-bold, 700); - color: #1e3c38; - margin: 0 0 12px 0; - } - - p { - font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - font-size: var(--font-size-lg, 1rem); - color: #697777; - margin: 0 0 28px 0; - } - - .shop-btn { - padding: 14px 32px; - background: #497671; - color: white; - text-decoration: none; - border-radius: var(--radius-lg, 13px); - font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - font-weight: var(--font-weight-semibold, 600); - font-size: var(--font-size-lg, 1rem); - transition: all 0.2s; - box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15); - - &:hover { - background: #3a5f5b; - transform: translateY(-2px); - box-shadow: 0 6px 12px rgba(73, 118, 113, 0.3); - } - } -} - -// Empty cart - alt -.cart-container.alt .empty-cart { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 100px 20px; - text-align: center; - background: white; - border-radius: 20px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); - - .empty-icon { - margin-bottom: 32px; - - svg { - width: 100px; - height: 100px; - opacity: 0.8; - } - } - - h2 { - font-size: var(--font-size-4xl, 2rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - margin: 0 0 12px 0; - } - - p { - font-size: var(--font-size-lg, 1rem); - color: #6b7280; - margin: 0 0 32px 0; - } - - .shop-btn { - padding: 14px 32px; - background: linear-gradient(135deg, #10b981 0%, #059669 100%); - color: white; - text-decoration: none; - border-radius: var(--radius-md, 12px); - font-weight: var(--font-weight-semibold, 600); - font-size: var(--font-size-lg, 1rem); - transition: all 0.3s; - box-shadow: 0 4px 16px rgba(16, 185, 129, 0.3); - - &:hover { - transform: translateY(-2px); - box-shadow: 0 6px 24px rgba(16, 185, 129, 0.4); - } - } } .cart-content { @@ -230,12 +69,6 @@ align-items: start; } -// alt wider summary -.cart-container.alt .cart-content { - grid-template-columns: minmax(0, 1fr) 400px; - gap: 32px; -} - .cart-items { display: flex; flex-direction: column; @@ -243,11 +76,6 @@ min-width: 0; } -// alt larger gap -.cart-container.alt .cart-items { - gap: 20px; -} - .cart-item-wrapper { position: relative; overflow: hidden; @@ -266,17 +94,12 @@ } } -// alt rounded corners -.cart-container.alt .cart-item-wrapper { - border-radius: 16px; -} - // platform cart item .cart-container.platform .cart-item { display: flex; gap: 20px; background: white; - border: 1px solid #d3dad9; + border: 1px solid var(--border-color); border-radius: var(--radius-lg, 13px); padding: 20px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); @@ -296,8 +119,8 @@ height: 100px; border-radius: var(--radius-lg, 13px); overflow: hidden; - background: #f5f3f9; - border: 1px solid #d3dad9; + background: var(--bg-secondary); + border: 1px solid var(--border-color); img { width: 100%; @@ -333,12 +156,12 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-lg, 1rem); font-weight: var(--font-weight-semibold, 600); - color: #1e3c38; + color: var(--text-primary); text-decoration: none; transition: color 0.2s; &:hover { - color: #497671; + color: var(--primary-color); } } @@ -361,7 +184,7 @@ .item-description { font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-base, 0.875rem); - color: #697777; + color: var(--text-secondary); line-height: 1.5; } @@ -374,7 +197,7 @@ .cart-variant { font-size: var(--font-size-sm, 0.8125rem); - color: #497671; + color: var(--primary-color); background: rgba(73, 118, 113, 0.08); padding: 3px 10px; border-radius: 6px; @@ -402,135 +225,6 @@ } } -// alt cart item - modern green theme -.cart-container.alt .cart-item { - display: flex; - gap: 20px; - background: white; - border: 1px solid #e5e7eb; - border-radius: 16px; - padding: 20px; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; - z-index: 1; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); - - &:hover { - border-color: #10b981; - box-shadow: 0 8px 24px rgba(16, 185, 129, 0.12); - transform: translateY(-2px); - } - - .item-image { - flex-shrink: 0; - width: 100px; - height: 100px; - border-radius: var(--radius-md, 12px); - overflow: hidden; - background: linear-gradient(135deg, #f0fdf4 0%, #d1fae5 100%); - border: 2px solid #d1fae5; - - img { - width: 100%; - height: 100%; - object-fit: contain; - background: white; - display: block; - transition: transform 0.3s; - } - - &:hover img { - transform: scale(1.05); - } - } - - .item-info { - flex: 1; - display: flex; - flex-direction: column; - gap: 10px; - min-width: 0; - } - - .item-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 16px; - } - - .item-name { - font-size: var(--font-size-xl, 1.125rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - text-decoration: none; - transition: color 0.2s; - - &:hover { - color: #10b981; - } - } - - .remove-btn { - flex-shrink: 0; - padding: 6px; - background: transparent; - border: none; - color: #9ca3af; - cursor: pointer; - border-radius: var(--radius-sm, 8px); - transition: all 0.2s; - - &:hover { - background: #fef2f2; - color: #ef4444; - transform: rotate(90deg); - } - } - - .item-description { - font-size: var(--font-size-base, 0.875rem); - color: #6b7280; - line-height: 1.6; - } - - .cart-item-variants { - display: flex; - gap: 10px; - flex-wrap: wrap; - align-items: center; - margin-top: 4px; - - .cart-variant { - font-size: var(--font-size-sm, 0.8125rem); - color: #6366f1; - background: rgba(99, 102, 241, 0.08); - padding: 3px 10px; - border-radius: 6px; - font-weight: var(--font-weight-medium, 500); - display: inline-flex; - align-items: center; - gap: 6px; - } - - .cart-colour-swatch { - display: inline-block; - width: 16px; - height: 16px; - border-radius: 50%; - border: 1px solid rgba(0, 0, 0, 0.15); - vertical-align: middle; - } - } - - .item-footer { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: auto; - } -} - // Pricing & Quantity - shared .item-pricing { display: flex; @@ -553,13 +247,13 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-xl, 1.125rem); font-weight: var(--font-weight-bold, 700); - color: #497671; + color: var(--primary-color); } .delivery-price { font-size: var(--font-size-sm, 0.8125rem); font-weight: var(--font-weight-medium, 500); - color: #697777; + color: var(--text-secondary); } } @@ -568,17 +262,17 @@ display: flex; align-items: center; gap: 12px; - background: #f5f3f9; + background: var(--bg-secondary); border-radius: var(--radius-lg, 13px); padding: 4px 10px; - border: 1px solid #d3dad9; + border: 1px solid var(--border-color); .qty-btn { width: 30px; height: 30px; border: none; background: transparent; - color: #497671; + color: var(--primary-color); cursor: pointer; display: flex; align-items: center; @@ -587,7 +281,7 @@ transition: all 0.2s; &:hover:not(:disabled) { - background: #497671; + background: var(--primary-color); color: white; } @@ -601,53 +295,7 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-lg, 1rem); font-weight: var(--font-weight-bold, 700); - color: #1e3c38; - min-width: 24px; - text-align: center; - } -} - -// alt quantity controls - modern green -.cart-container.alt .quantity-controls { - display: flex; - align-items: center; - gap: 14px; - background: linear-gradient(135deg, #f0fdf4 0%, #d1fae5 100%); - border-radius: 24px; - padding: 6px 12px; - border: 1px solid #d1fae5; - - .qty-btn { - width: 32px; - height: 32px; - border: none; - background: white; - color: #10b981; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; - transition: all 0.2s; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); - - &:hover:not(:disabled) { - background: #10b981; - color: white; - transform: scale(1.1); - box-shadow: 0 4px 8px rgba(16, 185, 129, 0.25); - } - - &:disabled { - opacity: 0.3; - cursor: not-allowed; - } - } - - .qty-value { - font-size: var(--font-size-lg, 1rem); - font-weight: var(--font-weight-bold, 700); - color: #059669; + color: var(--text-primary); min-width: 24px; text-align: center; } @@ -680,8 +328,8 @@ .cart-container.platform .cart-summary { position: sticky; top: 90px; - background: #f5f3f9; - border: 1px solid #d3dad9; + background: var(--bg-secondary); + border: 1px solid var(--border-color); border-radius: var(--radius-lg, 13px); padding: 28px; display: flex; @@ -693,7 +341,7 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-3xl, 1.5rem); font-weight: var(--font-weight-bold, 700); - color: #1e3c38; + color: var(--text-primary); margin: 0 0 16px 0; } @@ -703,7 +351,7 @@ align-items: center; font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-md, 0.9375rem); - color: #697777; + color: var(--text-secondary); &.delivery { display: flex; @@ -711,15 +359,15 @@ &.total { padding-top: 16px; - border-top: 1px solid #d3dad9; + border-top: 1px solid var(--border-color); font-size: var(--font-size-xl, 1.125rem); font-weight: var(--font-weight-bold, 700); - color: #1e3c38; + color: var(--text-primary); margin-top: 8px; .total-price { font-size: var(--font-size-3xl, 1.5rem); - color: #497671; + color: var(--primary-color); } } } @@ -734,7 +382,7 @@ .checkout-btn { width: 100%; padding: 16px; - background: #497671; + background: var(--primary-color); color: white; border: none; border-radius: var(--radius-lg, 13px); @@ -746,7 +394,7 @@ box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15); &:hover:not(:disabled) { - background: #3a5f5b; + background: var(--primary-hover); transform: translateY(-2px); box-shadow: 0 6px 16px rgba(73, 118, 113, 0.3); } @@ -827,163 +475,6 @@ } } -// alt Cart Summary - Green Modern -.cart-container.alt .cart-summary { - position: sticky; - top: 20px; - background: white; - border: none; - border-radius: 20px; - padding: 32px; - display: flex; - flex-direction: column; - gap: 20px; - box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08); - - .summary-header h3 { - font-size: var(--font-size-3xl, 1.5rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - margin: 0 0 20px 0; - background: linear-gradient(135deg, #059669 0%, #10b981 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - } - - .summary-row { - display: flex; - justify-content: space-between; - align-items: center; - font-size: var(--font-size-lg, 1rem); - color: #6b7280; - - &.delivery { - display: flex; - } - - &.total { - padding-top: 20px; - border-top: 2px solid #f0fdf4; - font-size: var(--font-size-2xl, 1.25rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - margin-top: 12px; - - .total-price { - font-size: var(--font-size-3xl, 1.5rem); - color: #10b981; - font-weight: 800; - } - } - - .value { - font-weight: var(--font-weight-semibold, 600); - color: #111827; - } - } - - .payment-method-actions { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; - margin-top: 12px; - } - - .checkout-btn { - width: 100%; - padding: 16px; - background: linear-gradient(135deg, #10b981 0%, #059669 100%); - color: white; - border: none; - border-radius: 14px; - font-size: var(--font-size-xl, 1.125rem); - font-weight: var(--font-weight-bold, 700); - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: 0 4px 16px rgba(16, 185, 129, 0.3); - - &:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(16, 185, 129, 0.4); - } - - &:active { - transform: translateY(0); - } - - &:disabled { - opacity: 0.5; - cursor: not-allowed; - } - } - - .card-payment-btn { - background: linear-gradient(135deg, #1f2937 0%, #111827 100%); - box-shadow: 0 4px 16px rgba(31, 41, 55, 0.22); - - &:hover:not(:disabled) { - box-shadow: 0 8px 24px rgba(31, 41, 55, 0.3); - } - } - - .cart-login-gate { - margin-top: 20px; - padding: 24px; - border-radius: 16px; - background: rgba(16, 185, 129, 0.04); - border: 1px dashed rgba(16, 185, 129, 0.3); - text-align: center; - - .login-gate-icon { - margin: 0 auto 12px; - width: 56px; - height: 56px; - border-radius: 50%; - background: rgba(16, 185, 129, 0.1); - color: #10b981; - display: flex; - align-items: center; - justify-content: center; - } - - .login-gate-title { - margin: 0 0 4px; - font-size: var(--font-size-lg, 1rem); - font-weight: var(--font-weight-bold, 700); - color: #111827; - } - - .login-gate-desc { - margin: 0 0 16px; - font-size: var(--font-size-sm, 0.8125rem); - color: #6b7280; - line-height: 1.4; - } - - .telegram-login-btn { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 12px 24px; - border: none; - border-radius: var(--radius-md, 12px); - background: #2AABEE; - color: #fff; - font-size: var(--font-size-md, 0.9375rem); - font-weight: var(--font-weight-semibold, 600); - cursor: pointer; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - - &:hover { - background: #229ED9; - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(42, 171, 238, 0.3); - } - } - } -} - // Terms agreement - shared base .terms-agreement { margin-top: 12px; @@ -1061,17 +552,11 @@ font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; } -.cart-container.alt .cart-summary .delivery-warning { - color: #92400e; - background: #fffbeb; - border: 1px solid #fde68a; -} - // platform checkbox colors .cart-container.platform .terms-agreement .checkbox-container { input[type="checkbox"]:checked ~ .checkmark { - background: #497671; - border-color: #497671; + background: var(--primary-color); + border-color: var(--primary-color); &::after { display: block; @@ -1079,55 +564,24 @@ } .checkmark { - border: 2px solid #d3dad9; + border: 2px solid var(--border-color); border-radius: var(--radius-xs, 4px); } .terms-text { font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: var(--font-size-sm, 0.8125rem); - color: #697777; + color: var(--text-secondary); line-height: 1.5; a { - color: #497671; + color: var(--primary-color); text-decoration: none; font-weight: var(--font-weight-semibold, 600); &:hover { text-decoration: underline; - color: #3a5f5b; - } - } - } -} - -// alt checkbox colors - green -.cart-container.alt .terms-agreement .checkbox-container { - input[type="checkbox"]:checked ~ .checkmark { - background: #10b981; - border-color: #10b981; - - &::after { - display: block; - } - } - - .checkmark { - border: 2px solid #d1fae5; - border-radius: 6px; - } - - .terms-text { - font-size: var(--font-size-base, 0.875rem); - line-height: 1.6; - - a { - color: #10b981; - font-weight: var(--font-weight-semibold, 600); - - &:hover { - color: #059669; + color: var(--primary-hover); } } } @@ -1157,7 +611,7 @@ position: relative; max-height: 90vh; overflow-y: auto; - border: 1px solid #d3dad9; + border: 1px solid var(--border-color); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12); } .close-modal-btn { @@ -1275,7 +729,7 @@ .retry-payment-btn { padding: 14px 24px; - background: #497671; + background: var(--primary-color); color: white; border: none; border-radius: var(--radius-lg, 13px); @@ -1286,7 +740,7 @@ transition: all 0.2s; &:hover { - background: #3a5f5b; + background: var(--primary-hover); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(73, 118, 113, 0.3); } @@ -1310,8 +764,8 @@ .spinner-small { width: 50px; height: 50px; - border: 4px solid #d3dad9; - border-top: 4px solid #497671; + border: 4px solid var(--border-color); + border-top: 4px solid var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto; @@ -1362,9 +816,9 @@ left: 16px; right: 16px; height: 2px; - background: linear-gradient(90deg, transparent, #497671, transparent); + background: linear-gradient(90deg, transparent, var(--primary-color), transparent); animation: scan 2s linear infinite; - box-shadow: 0 0 10px #497671; + box-shadow: 0 0 10px var(--primary-color); } @keyframes scan { @@ -1414,7 +868,7 @@ .pulse-dot { width: 8px; height: 8px; - background: #497671; + background: var(--primary-color); border-radius: 50%; animation: pulse 1.5s ease-in-out infinite; } @@ -1558,7 +1012,7 @@ transition: all 0.2s; &:focus { - border-color: #497671; + border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(73, 118, 113, 0.1); } @@ -1585,7 +1039,7 @@ .submit-email-btn { padding: 14px; - background: #497671; + background: var(--primary-color); color: white; border: none; border-radius: var(--radius-lg, 13px); @@ -1600,7 +1054,7 @@ transition: all 0.2s; &:hover:not(:disabled) { - background: #3a5f5b; + background: var(--primary-hover); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(73, 118, 113, 0.3); } @@ -1619,11 +1073,6 @@ gap: 20px; } - .cart-container.alt .cart-content { - grid-template-columns: minmax(0, 1fr); - gap: 20px; - } - .cart-summary { position: static; width: 100%; @@ -1631,12 +1080,10 @@ min-width: 0; } - .cart-container.alt, .cart-container.platform { padding: 16px; } - .cart-container.alt .cart-header, .cart-container.platform .cart-header { flex-wrap: wrap; gap: 12px; @@ -1652,7 +1099,7 @@ .payment-modal { padding: 24px; - padding-top: 56px; // Äîïîëíèòåëüíûé îòñòóï ñâåðõó äëÿ êíîïêè çàêðûòèÿ + padding-top: 56px; // �������������� ������ ������ ��� ������ �������� } .close-modal-btn { @@ -1708,535 +1155,3 @@ display: none !important; } } - -/* ============================================= - alt THEME STYLES - Modern Cart Design - ============================================= */ - -.alt-cart-container { - max-width: 1400px; - margin: 0 auto; - padding: 2rem; - min-height: calc(100vh - 200px); -} - -.alt-cart-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 2rem; - padding-bottom: 1.5rem; - border-bottom: 2px solid var(--border-color); - - h1 { - font-size: var(--font-size-4xl, 2rem); - font-weight: var(--font-weight-bold, 700); - color: var(--text-primary); - margin: 0; - background: linear-gradient(135deg, #10b981 0%, #14b8a6 50%, #06b6d4 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - } - - .alt-clear-btn { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1.25rem; - background: linear-gradient(135deg, #ef4444, #dc2626); - color: white; - border: none; - border-radius: var(--radius-lg); - font-size: var(--font-size-md, 0.9375rem); - font-weight: var(--font-weight-semibold, 600); - cursor: pointer; - transition: all 0.3s ease; - - svg { - width: 18px; - height: 18px; - } - - &:hover { - transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(239, 68, 68, 0.3); - } - - &:active { - transform: translateY(0); - } - } -} - -.alt-empty-cart { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 4rem 2rem; - text-align: center; - background: var(--bg-secondary); - border-radius: var(--radius-xl); - margin: 2rem 0; - - .empty-icon { - margin-bottom: 2rem; - - svg { - width: 100px; - height: 100px; - opacity: 0.6; - } - } - - h2 { - font-size: var(--font-size-4xl, 2rem); - font-weight: var(--font-weight-bold, 700); - color: var(--text-primary); - margin: 0 0 0.75rem 0; - } - - p { - font-size: var(--font-size-lg, 1rem); - color: var(--text-secondary); - margin: 0 0 2rem 0; - max-width: 400px; - } - - .alt-shop-btn { - display: inline-block; - padding: 0.875rem 2rem; - background: linear-gradient(135deg, #10b981, #14b8a6, #06b6d4); - color: white; - text-decoration: none; - border-radius: var(--radius-lg); - font-weight: var(--font-weight-semibold, 600); - font-size: var(--font-size-lg, 1rem); - transition: all 0.3s ease; - - &:hover { - transform: translateY(-2px); - box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3); - } - } -} - -.alt-cart-content { - display: grid; - grid-template-columns: 1fr 400px; - gap: 2rem; - align-items: start; -} - -.alt-cart-items { - display: flex; - flex-direction: column; - gap: 1.25rem; -} - -.alt-cart-item { - display: flex; - gap: 1.5rem; - padding: 1.5rem; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - transition: all 0.3s ease; - - &:hover { - border-color: #10b981; - box-shadow: 0 4px 16px rgba(16, 185, 129, 0.1); - transform: translateY(-2px); - } - - .alt-item-image { - flex-shrink: 0; - width: 120px; - height: 120px; - border-radius: var(--radius-md); - overflow: hidden; - background: white; - border: 1px solid var(--border-color); - - img { - width: 100%; - height: 100%; - object-fit: contain; - background: white; - transition: transform 0.3s ease; - } - - &:hover img { - transform: scale(1.05); - } - } - - .alt-item-details { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.75rem; - min-width: 0; - - .item-top { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 1rem; - - .item-name { - font-size: var(--font-size-xl, 1.125rem); - font-weight: var(--font-weight-semibold, 600); - color: var(--text-primary); - text-decoration: none; - margin: 0; - transition: color 0.2s; - - &:hover { - color: #10b981; - } - } - - .alt-remove-btn { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - background: transparent; - border: none; - border-radius: var(--radius-md); - color: var(--text-secondary); - cursor: pointer; - transition: all 0.2s ease; - - svg { - width: 20px; - height: 20px; - } - - &:hover { - background: rgba(239, 68, 68, 0.1); - color: #ef4444; - } - } - } - - .item-desc { - font-size: var(--font-size-base, 0.875rem); - color: var(--text-secondary); - margin: 0; - line-height: 1.5; - display: -webkit-box; - line-clamp: 2; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - } - - .item-bottom { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: auto; - gap: 1rem; - - .item-price { - font-weight: var(--font-weight-bold, 700); - font-size: var(--font-size-2xl, 1.25rem); - - .price-discount { - display: flex; - align-items: center; - gap: 0.5rem; - - .old { - font-size: var(--font-size-md, 0.9375rem); - color: var(--text-secondary); - text-decoration: line-through; - font-weight: var(--font-weight-normal, 400); - } - - .current { - color: #10b981; - font-size: var(--font-size-2xl, 1.25rem); - } - } - - .current { - color: var(--text-primary); - } - } - - .alt-quantity { - display: flex; - align-items: center; - gap: 0.5rem; - background: white; - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: 0.25rem; - - button { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - background: transparent; - border: none; - border-radius: var(--radius-sm); - color: var(--text-primary); - cursor: pointer; - transition: all 0.2s ease; - - svg { - width: 16px; - height: 16px; - } - - &:hover:not(:disabled) { - background: var(--bg-secondary); - } - - &:disabled { - opacity: 0.3; - cursor: not-allowed; - } - } - - span { - min-width: 36px; - text-align: center; - font-weight: var(--font-weight-semibold, 600); - font-size: var(--font-size-lg, 1rem); - color: var(--text-primary); - } - } - } - } -} - -.alt-cart-summary { - position: sticky; - top: 80px; -} - -.summary-card { - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 1.5rem; - - h3 { - font-size: var(--font-size-2xl, 1.25rem); - font-weight: var(--font-weight-bold, 700); - color: var(--text-primary); - margin: 0 0 1.25rem 0; - padding-bottom: 1rem; - border-bottom: 1px solid var(--border-color); - } - - .summary-row { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.75rem 0; - font-size: var(--font-size-md, 0.9375rem); - color: var(--text-secondary); - - .value { - font-weight: var(--font-weight-semibold, 600); - color: var(--text-primary); - } - } - - .summary-total { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1.25rem 0; - margin-top: 1rem; - border-top: 1px solid var(--border-color); - font-weight: var(--font-weight-bold, 700); - font-size: var(--font-size-xl, 1.125rem); - - span:first-child { - color: var(--text-secondary); - } - - .total-price { - font-size: var(--font-size-3xl, 1.5rem); - background: linear-gradient(135deg, #10b981, #14b8a6, #06b6d4); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - } - } - - .alt-checkout-btn { - width: 100%; - padding: 1rem; - margin-top: 1.25rem; - background: linear-gradient(135deg, #10b981, #14b8a6, #06b6d4); - color: white; - border: none; - border-radius: var(--radius-md); - font-size: 1.0625rem; - font-weight: var(--font-weight-bold, 700); - cursor: pointer; - transition: all 0.3s ease; - box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); - - &:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(16, 185, 129, 0.4); - } - - &:active:not(:disabled) { - transform: translateY(0); - } - - &:disabled { - opacity: 0.5; - cursor: not-allowed; - transform: none; - } - } - - .alt-terms-agreement { - margin-top: 1rem; - - .alt-checkbox-container { - display: flex; - align-items: flex-start; - gap: 0.75rem; - cursor: pointer; - position: relative; - font-size: var(--font-size-base, 0.875rem); - line-height: 1.6; - - input[type="checkbox"] { - position: absolute; - opacity: 0; - cursor: pointer; - height: 0; - width: 0; - - &:checked ~ .alt-checkmark { - background: #10b981; - border-color: #10b981; - - &::after { - display: block; - } - } - } - - .alt-checkmark { - position: relative; - flex-shrink: 0; - height: 20px; - width: 20px; - background-color: transparent; - border: 2px solid var(--border-color); - border-radius: var(--radius-xs, 4px); - transition: all 0.2s ease; - margin-top: 2px; - - &::after { - content: ""; - position: absolute; - display: none; - left: 6px; - top: 2px; - width: 4px; - height: 9px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); - } - } - - .alt-terms-text { - color: var(--text-secondary); - line-height: 1.6; - - a { - color: #10b981; - text-decoration: none; - font-weight: var(--font-weight-medium, 500); - transition: all 0.2s; - - &:hover { - text-decoration: underline; - color: #059669; - } - } - } - } - } -} - -/* alt Cart Responsive */ -@media (max-width: 1024px) { - .alt-cart-content { - grid-template-columns: 1fr; - - .alt-cart-summary { - position: static; - } - } -} - -@media (max-width: 768px) { - .alt-cart-container { - padding: 1rem; - } - - .alt-cart-header { - flex-direction: column; - align-items: flex-start; - gap: 1rem; - - h1 { - font-size: var(--font-size-3xl, 1.5rem); - } - } - - .alt-cart-item { - flex-direction: column; - gap: 1rem; - - .alt-item-image { - width: 100%; - height: 200px; - } - - .alt-item-details { - .item-bottom { - flex-direction: column; - align-items: stretch; - gap: 0.75rem; - - .alt-quantity { - justify-content: center; - } - } - } - } - - .summary-card { - padding: 1.25rem; - - .summary-total .total-price { - font-size: var(--font-size-2xl, 1.25rem); - } - } -} - - diff --git a/src/app/pages/cart/cart.component.ts b/src/app/pages/cart/cart.component.ts index 48b2efb..4abeea9 100644 --- a/src/app/pages/cart/cart.component.ts +++ b/src/app/pages/cart/cart.component.ts @@ -15,6 +15,8 @@ import { TranslatePipe } from '../../i18n/translate.pipe'; import { TranslateService } from '../../i18n/translate.service'; import { PAYMENT_POLL_INTERVAL_MS, PAYMENT_MIN_POLL_SECONDS, PAYMENT_TIMEOUT_CLOSE_MS, LINK_COPIED_DURATION_MS } from '../../config/constants'; import { IconComponent } from '../../shared/ui/icon/icon.component'; +import { EmptyStateComponent } from '../../shared/ui/empty-state/empty-state.component'; +import { ButtonComponent } from '../../shared/ui/button/button.component'; import { ConfigService } from '../../core/config/config.service'; import { TenantResolverService } from '../../core/config/tenant-resolver.service'; @@ -22,7 +24,7 @@ type PaymentMethod = 'qr' | 'card'; @Component({ selector: 'app-cart', - imports: [DecimalPipe, RouterLink, FormsModule, DeliverySelectorComponent, TelegramLoginComponent, LangRoutePipe, TranslatePipe, IconComponent], + imports: [DecimalPipe, RouterLink, FormsModule, DeliverySelectorComponent, TelegramLoginComponent, LangRoutePipe, TranslatePipe, IconComponent, EmptyStateComponent, ButtonComponent], templateUrl: './cart.component.html', styleUrls: ['./cart.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush diff --git a/src/app/pages/static-page/static-page.component.html b/src/app/pages/static-page/static-page.component.html index 14f0d43..33d3ac7 100644 --- a/src/app/pages/static-page/static-page.component.html +++ b/src/app/pages/static-page/static-page.component.html @@ -1,11 +1,18 @@
@if (loading()) { -
{{ 'app.connecting' | translate }}
+
+ + + + +
} @else if (notFound()) {
-

404

-

{{ 'staticPages.notFound' | translate }}

- {{ 'staticPages.backHome' | translate }} + +
+ {{ 'staticPages.backHome' | translate }} +
+
} @else {
diff --git a/src/app/pages/static-page/static-page.component.scss b/src/app/pages/static-page/static-page.component.scss index a0cb0db..e268d97 100644 --- a/src/app/pages/static-page/static-page.component.scss +++ b/src/app/pages/static-page/static-page.component.scss @@ -3,24 +3,9 @@ } .static-page__state { - text-align: center; padding: 2rem 0; - color: var(--text-secondary, #667a77); - - h1 { - margin-bottom: 0.5rem; - color: var(--text-primary, #1e3c38); - } - - a { - color: var(--primary-color, #497671); - text-decoration: none; - - &:focus-visible { - outline: 2px solid var(--primary-color, #497671); - outline-offset: 2px; - } - } + display: grid; + gap: 0.75rem; } .static-page__content { diff --git a/src/app/pages/static-page/static-page.component.ts b/src/app/pages/static-page/static-page.component.ts index cb1f009..247855b 100644 --- a/src/app/pages/static-page/static-page.component.ts +++ b/src/app/pages/static-page/static-page.component.ts @@ -6,11 +6,14 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { StaticPageResolverService } from '../../core/config/static-page-resolver.service'; import { LanguageService } from '../../services/language.service'; import { TranslatePipe } from '../../i18n/translate.pipe'; +import { EmptyStateComponent } from '../../shared/ui/empty-state/empty-state.component'; +import { SkeletonComponent } from '../../shared/ui/skeleton/skeleton.component'; +import { ButtonComponent } from '../../shared/ui/button/button.component'; @Component({ selector: 'app-static-page', standalone: true, - imports: [CommonModule, RouterLink, TranslatePipe], + imports: [CommonModule, RouterLink, TranslatePipe, EmptyStateComponent, SkeletonComponent, ButtonComponent], templateUrl: './static-page.component.html', styleUrls: ['./static-page.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush