color
This commit is contained in:
@@ -102,19 +102,19 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (availableColours().length || availableSizes().length || item()!.colour || item()!.size) {
|
@if (availableColours().length || availableSizes().length || item()!.colour || (item()!.size && item()!.size!.toLowerCase() !== 'default')) {
|
||||||
<div class="novo-variants">
|
<div class="novo-variants">
|
||||||
@if (availableColours().length) {
|
@if (availableColours().length) {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||||
@for (c of availableColours(); track c) {
|
@for (c of availableColours(); track c) {
|
||||||
<span class="variant-chip colour-chip" [class.active]="selectedColour() === c" (click)="selectColour(c)">{{ c }}</span>
|
<span class="colour-swatch" [class.active]="selectedColour() === c" [style.background-color]="c" [title]="c" (click)="selectColour(c)"></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
} @else if (item()!.colour) {
|
} @else if (item()!.colour) {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||||
<span class="variant-chip colour-chip active">{{ item()!.colour }}</span>
|
<span class="colour-swatch active" [style.background-color]="item()!.colour" [title]="item()!.colour"></span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (availableSizes().length) {
|
@if (availableSizes().length) {
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
} @else if (item()!.size) {
|
} @else if (item()!.size && item()!.size!.toLowerCase() !== 'default') {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||||
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
||||||
@@ -381,19 +381,19 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (availableColours().length || availableSizes().length || item()!.colour || item()!.size) {
|
@if (availableColours().length || availableSizes().length || item()!.colour || (item()!.size && item()!.size!.toLowerCase() !== 'default')) {
|
||||||
<div class="dx-variants">
|
<div class="dx-variants">
|
||||||
@if (availableColours().length) {
|
@if (availableColours().length) {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||||
@for (c of availableColours(); track c) {
|
@for (c of availableColours(); track c) {
|
||||||
<span class="variant-chip colour-chip" [class.active]="selectedColour() === c" (click)="selectColour(c)">{{ c }}</span>
|
<span class="colour-swatch" [class.active]="selectedColour() === c" [style.background-color]="c" [title]="c" (click)="selectColour(c)"></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
} @else if (item()!.colour) {
|
} @else if (item()!.colour) {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.colour' | translate }}:</span>
|
||||||
<span class="variant-chip colour-chip active">{{ item()!.colour }}</span>
|
<span class="colour-swatch active" [style.background-color]="item()!.colour" [title]="item()!.colour"></span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (availableSizes().length) {
|
@if (availableSizes().length) {
|
||||||
@@ -403,7 +403,7 @@
|
|||||||
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
<span class="variant-chip size-chip" [class.active]="selectedSize() === s" (click)="selectSize(s)">{{ s }}</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
} @else if (item()!.size) {
|
} @else if (item()!.size && item()!.size!.toLowerCase() !== 'default') {
|
||||||
<div class="variant-group">
|
<div class="variant-group">
|
||||||
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
<span class="variant-label">{{ 'itemDetail.size' | translate }}:</span>
|
||||||
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
<span class="variant-chip size-chip active">{{ item()!.size }}</span>
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ $dx-card-bg: #f5f3f9;
|
|||||||
// Variant chips (colour/size) — shared between dexar and novo
|
// Variant chips (colour/size) — shared between dexar and novo
|
||||||
.dx-variants, .novo-variants {
|
.dx-variants, .novo-variants {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
|
||||||
@@ -304,6 +304,7 @@ $dx-card-bg: #f5f3f9;
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variant-label {
|
.variant-label {
|
||||||
@@ -335,6 +336,25 @@ $dx-card-bg: #f5f3f9;
|
|||||||
box-shadow: 0 0 0 2px rgba(73, 118, 113, 0.25);
|
box-shadow: 0 0 0 2px rgba(73, 118, 113, 0.25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colour-swatch {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid $dx-border;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.15s, box-shadow 0.15s;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $dx-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: $dx-primary;
|
||||||
|
box-shadow: 0 0 0 2px rgba(73, 118, 113, 0.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dx-attributes, .novo-attributes {
|
.dx-attributes, .novo-attributes {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
|
|||||||
const filtered = colour
|
const filtered = colour
|
||||||
? details.filter(d => (d.colour || d.color) === colour)
|
? details.filter(d => (d.colour || d.color) === colour)
|
||||||
: details;
|
: details;
|
||||||
const unique = [...new Set(filtered.map(d => d.size).filter((s): s is string => !!s))];
|
const unique = [...new Set(filtered.map(d => d.size).filter((s): s is string => !!s && s.toLowerCase() !== 'default'))];
|
||||||
return unique;
|
return unique;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ export class ApiService {
|
|||||||
return map[apiLang] || apiLang.toLowerCase();
|
return map[apiLang] || apiLang.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Convert Go-style hex colour (0xfffca0) → CSS hex (#fffca0) */
|
||||||
|
private normalizeColor(c: string): string {
|
||||||
|
if (!c) return '';
|
||||||
|
return c.startsWith('0x') ? '#' + c.slice(2) : c;
|
||||||
|
}
|
||||||
|
|
||||||
/** Resolve relative image URLs (e.g. ./images/x.webp) against site origin */
|
/** Resolve relative image URLs (e.g. ./images/x.webp) against site origin */
|
||||||
private resolveImageUrl(url: string): string {
|
private resolveImageUrl(url: string): string {
|
||||||
if (!url) return '';
|
if (!url) return '';
|
||||||
@@ -46,10 +52,14 @@ export class ApiService {
|
|||||||
const details = raw.itemDetails || raw.itemdetails;
|
const details = raw.itemDetails || raw.itemdetails;
|
||||||
if (details && Array.isArray(details) && details.length > 0) {
|
if (details && Array.isArray(details) && details.length > 0) {
|
||||||
const detail = details[0];
|
const detail = details[0];
|
||||||
item.itemDetails = raw.itemDetails;
|
item.itemDetails = details.map((d: any) => ({
|
||||||
|
...d,
|
||||||
|
colour: this.normalizeColor(d.colour || d.color || ''),
|
||||||
|
color: undefined,
|
||||||
|
}));
|
||||||
if (item.price == null || item.price === 0) item.price = detail.price;
|
if (item.price == null || item.price === 0) item.price = detail.price;
|
||||||
if (!item.currency) item.currency = detail.currency;
|
if (!item.currency) item.currency = detail.currency;
|
||||||
if (!item.colour) item.colour = detail.colour || detail.color || '';
|
if (!item.colour) item.colour = this.normalizeColor(detail.colour || detail.color || '');
|
||||||
if (!item.size) item.size = detail.size || '';
|
if (!item.size) item.size = detail.size || '';
|
||||||
// Use remaining from detail for stock level
|
// Use remaining from detail for stock level
|
||||||
if (raw.remaining == null && detail.remaining != null) {
|
if (raw.remaining == null && detail.remaining != null) {
|
||||||
@@ -111,7 +121,7 @@ export class ApiService {
|
|||||||
item.attributes = raw.attributes || [];
|
item.attributes = raw.attributes || [];
|
||||||
|
|
||||||
// Preserve colour & size (only if not already set from itemDetails)
|
// Preserve colour & size (only if not already set from itemDetails)
|
||||||
if (!item.colour) item.colour = raw.colour || '';
|
if (!item.colour) item.colour = this.normalizeColor(raw.colour || '');
|
||||||
if (!item.size) item.size = raw.size || '';
|
if (!item.size) item.size = raw.size || '';
|
||||||
|
|
||||||
// Map backOffice comments → legacy callbacks
|
// Map backOffice comments → legacy callbacks
|
||||||
|
|||||||
Reference in New Issue
Block a user