Add a tier number and category label to package cards
Inspired by a reference mockup showing a numbered, categorized tier lineup (Einstieg/Upgrade/.../Referenz). Each card now shows its price rank (01, 02...) plus an auto-derived category eyebrow label, computed the same way as the material-tier color system so it needs no extra admin config and scales to any package count. Kept the existing responsive grid rather than switching to a fixed horizontal row, since the fixed layout looks broken for models with only 1-2 packages. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
dea2a936a1
commit
bac6d114a2
3 changed files with 12 additions and 1 deletions
|
|
@ -155,6 +155,7 @@ export default {
|
|||
productLoading: 'Produkt wird geladen…',
|
||||
requestContact: 'Kontakt anfragen',
|
||||
featuredBadge: 'Empfohlen',
|
||||
tierLabels: ['Einstieg', 'Upgrade', 'Performance', 'Premium', 'High-End', 'Signature', 'Referenz'],
|
||||
},
|
||||
leistungen: {
|
||||
metaTitle: 'Leistungen',
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ export default {
|
|||
productLoading: 'Loading product…',
|
||||
requestContact: 'Request contact',
|
||||
featuredBadge: 'Recommended',
|
||||
tierLabels: ['Entry', 'Upgrade', 'Performance', 'Premium', 'High-End', 'Signature', 'Reference'],
|
||||
},
|
||||
leistungen: {
|
||||
metaTitle: 'Services',
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ export default function ModelPage() {
|
|||
// oben. Das braucht keine zusaetzliche Admin-Einstellung und passt sich automatisch
|
||||
// an jede Paketanzahl an.
|
||||
const materials = theme === 'dark' ? MATERIALS_DARK : MATERIALS_LIGHT;
|
||||
const tierLabels = t('modelPage.tierLabels');
|
||||
const rankById = new Map(
|
||||
[...packages].sort((a, b) => a.total_price - b.total_price).map((p, i) => [p.id, i])
|
||||
);
|
||||
|
|
@ -118,6 +119,8 @@ export default function ModelPage() {
|
|||
const n = packages.length;
|
||||
const rank = rankById.get(pkg.id) ?? 0;
|
||||
const tierT = n <= 1 ? 0 : rank / (n - 1);
|
||||
const tierNumber = String(rank + 1).padStart(2, '0');
|
||||
const tierLabel = tierLabels[Math.min(Math.floor(tierT * tierLabels.length), tierLabels.length - 1)];
|
||||
|
||||
const bgRgb = materialRgbAt(materials, tierT, 'bg').map(Math.round);
|
||||
const accentRgbFloat = materialRgbAt(materials, tierT, 'accent');
|
||||
|
|
@ -151,6 +154,8 @@ export default function ModelPage() {
|
|||
return {
|
||||
isDarkCard,
|
||||
mutedColor,
|
||||
tierNumber,
|
||||
tierLabel,
|
||||
priceColor: `rgb(${priceRgb.join(', ')})`,
|
||||
iconChipStyle: {
|
||||
backgroundColor: `rgba(${accentRgb.join(', ')}, 0.16)`,
|
||||
|
|
@ -198,7 +203,7 @@ export default function ModelPage() {
|
|||
|
||||
<div className="grid gap-6 sm:grid-cols-2 xl:grid-cols-3">
|
||||
{packages.map((pkg) => {
|
||||
const { isDarkCard, style, priceColor, mutedColor, iconChipStyle } = styleOf(pkg);
|
||||
const { isDarkCard, style, priceColor, mutedColor, iconChipStyle, tierNumber, tierLabel } = styleOf(pkg);
|
||||
|
||||
return (
|
||||
<div key={pkg.id} style={style} className="relative flex flex-col rounded-xl border p-6">
|
||||
|
|
@ -208,6 +213,10 @@ export default function ModelPage() {
|
|||
</span>
|
||||
)}
|
||||
|
||||
<p style={{ color: mutedColor }} className="mb-2 text-xs font-semibold uppercase tracking-wider">
|
||||
{tierNumber} · {tierLabel}
|
||||
</p>
|
||||
|
||||
{pkg.icon_name && (
|
||||
<div style={iconChipStyle} className="mb-3 flex h-11 w-11 items-center justify-center rounded-full">
|
||||
<DynamicIcon name={pkg.icon_name} className="h-6 w-6" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue