{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "loyalty-rewards-tier-hub",
  "title": "Loyalty Rewards Tier Hub",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/loyalty-rewards-tier-hub/LoyaltyRewardsTierHub.vue",
      "content": "<script lang=\"ts\">\nexport interface LoyaltyPerk {\n  id: string\n  title: string\n  subtitle: string\n  description: string\n  status: 'active' | 'locked'\n  tierBadge: string\n  unlockPoints?: number\n}\n\nexport interface LoyaltyReward {\n  id: string\n  title: string\n  category: string\n  pointsCost: number\n  description: string\n  unlocked: boolean\n  pointsNeeded?: number\n  code?: string\n}\n\nexport interface LoyaltyLedgerEntry {\n  id: string\n  title: string\n  subtitle: string\n  type: string\n  date: string\n  pointsChange: number\n  isPositive: boolean\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  Award,\n  Check,\n  Crown,\n  Gift,\n  Headphones,\n  History,\n  Lock,\n  ShoppingBag,\n  Tag,\n  Ticket,\n  Truck,\n  Zap,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\ninterface Props {\n  customerName?: string\n  tierName?: string\n  currentPoints?: number\n  targetPoints?: number\n  pointValueDollars?: number\n  multiplier?: string\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  customerName: 'Elena Rostova',\n  tierName: 'VIP Platinum Member',\n  currentPoints: 2450,\n  targetPoints: 3000,\n  pointValueDollars: 24.5,\n  multiplier: '2x Points Multiplier',\n})\n\nconst redeemedMap = ref<Record<string, boolean>>({})\n\nfunction handleRedeem(rewardId: string) {\n  redeemedMap.value[rewardId] = true\n}\n\nconst perks: LoyaltyPerk[] = [\n  {\n    id: 'perk-shipping',\n    title: 'Free Express Shipping on All Orders',\n    subtitle: 'All Orders',\n    description: 'Complimentary 2-day express shipping on every online order with zero minimum spend.',\n    status: 'active',\n    tierBadge: 'Active',\n  },\n  {\n    id: 'perk-archive',\n    title: 'Early Access to Private Archive Sales',\n    subtitle: '48h Early Access',\n    description: 'Shop seasonal private archives and limited capsule releases 48 hours before public launch.',\n    status: 'active',\n    tierBadge: 'Active',\n  },\n  {\n    id: 'perk-stylist',\n    title: 'Dedicated VIP Concierge & Personal Stylist',\n    subtitle: '1-on-1 Stylist Line',\n    description: 'Direct priority chat with our senior stylists for bespoke fashion curation and concierge care.',\n    status: 'active',\n    tierBadge: 'Active',\n  },\n  {\n    id: 'perk-annual-gift',\n    title: 'Diamond Exclusive Annual Gift',\n    subtitle: 'Bespoke Curated Box',\n    description: 'Curated luxury anniversary gift box ($120+ retail value) delivered automatically each winter.',\n    status: 'locked',\n    tierBadge: 'Unlocks at 3,000 pts',\n    unlockPoints: 3000,\n  },\n]\n\nconst rewards: LoyaltyReward[] = [\n  {\n    id: 'reward-15-off',\n    title: '$15 Off Any Order',\n    category: 'Store Credit Voucher',\n    pointsCost: 1500,\n    description: 'Instant digital coupon applied at checkout on any order above $50.',\n    unlocked: true,\n    code: 'VIP-SAVE15',\n  },\n  {\n    id: 'reward-leather-pouch',\n    title: 'Free Travel Leather Pouch',\n    category: 'Exclusive Merchandise',\n    pointsCost: 2000,\n    description: 'Handcrafted Italian pebbled leather travel accessory pouch in signature Midnight Noir.',\n    unlocked: true,\n    code: 'CLAIM-POUCH24',\n  },\n  {\n    id: 'reward-audio-30',\n    title: '$30 Off Premium Audio',\n    category: 'Partner Exclusive',\n    pointsCost: 3000,\n    description: 'Exclusive member markdown on noise-cancelling headphones and studio sound gear.',\n    unlocked: false,\n    pointsNeeded: 550,\n  },\n]\n\nconst ledgerTransactions: LoyaltyLedgerEntry[] = [\n  {\n    id: 'tx-1',\n    title: 'Order #ORD-9428 - Studio Silk Blouse',\n    subtitle: 'Online Purchase · $190.00 subtotal',\n    type: 'Earned · 2x Platinum Multiplier',\n    date: 'Oct 18, 2024',\n    pointsChange: 380,\n    isPositive: true,\n  },\n  {\n    id: 'tx-2',\n    title: 'Redeemed: $10 Voucher Code #VIP-10OFF',\n    subtitle: 'Rewards Catalog · Checkout Redemption',\n    type: 'Reward Redemption',\n    date: 'Oct 10, 2024',\n    pointsChange: -1000,\n    isPositive: false,\n  },\n  {\n    id: 'tx-3',\n    title: 'Order #ORD-9104 - Cashmere Wrap',\n    subtitle: 'Online Purchase · $320.00 subtotal',\n    type: 'Earned · 2x Platinum Multiplier',\n    date: 'Sep 29, 2024',\n    pointsChange: 640,\n    isPositive: true,\n  },\n  {\n    id: 'tx-4',\n    title: 'Tier Upgrade Bonus - Platinum Milestone',\n    subtitle: 'Milestone Threshold · 2,000 pts Achieved',\n    type: 'Milestone Tier Reward',\n    date: 'Sep 15, 2024',\n    pointsChange: 500,\n    isPositive: true,\n  },\n]\n</script>\n\n<template>\n  <div data-slot=\"loyalty-rewards-tier-hub\" :class=\"cn('mx-auto w-full max-w-5xl space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n      <div>\n        <div class=\"flex items-center gap-2\">\n          <Badge wrap variant=\"secondary\" class=\"gap-1.5 font-medium\">\n            <Award class=\"text-primary size-3.5\" aria-hidden=\"true\" />\n            VIP Rewards Club\n          </Badge>\n        </div>\n        <h1 class=\"text-foreground mt-2 text-2xl font-bold tracking-tight sm:text-3xl\">Loyalty &amp; Rewards Hub</h1>\n        <p class=\"text-muted-foreground mt-1 max-w-2xl text-sm sm:text-base\">\n          Track VIP tier progress, redeem points for luxury perks, and review your member transaction ledger.\n        </p>\n      </div>\n    </div>\n\n    <!-- Customer Loyalty Hero Card -->\n    <Card class=\"border-border/80 shadow-xs\">\n      <CardContent class=\"space-y-6 p-6\">\n        <!-- Profile Header & Tier Status -->\n        <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n          <div class=\"flex items-center gap-4\">\n            <Avatar class=\"border-primary/20 size-14 border-2 shadow-xs\">\n              <AvatarFallback class=\"bg-primary/10 text-primary text-base font-semibold\"> ER </AvatarFallback>\n            </Avatar>\n            <div>\n              <h2 class=\"text-foreground text-lg font-bold tracking-tight sm:text-xl\">\n                {{ props.customerName }}\n              </h2>\n              <p class=\"text-muted-foreground text-xs font-medium sm:text-sm\">\n                {{ props.tierName }} · Member since 2022\n              </p>\n            </div>\n          </div>\n\n          <Badge\n            wrap\n            variant=\"outline\"\n            class=\"border-primary/20 bg-primary/10 text-primary gap-1.5 px-3 py-1.5 text-xs font-semibold\"\n          >\n            <Crown class=\"text-primary size-3.5 shrink-0\" aria-hidden=\"true\" />\n            <span>Platinum Tier · 2x Points Multiplier</span>\n          </Badge>\n        </div>\n\n        <Separator />\n\n        <!-- Points Balance & Multiplier Display -->\n        <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n          <!-- Balance Stat -->\n          <div class=\"border-border/60 bg-muted/30 flex flex-col justify-between rounded-xl border p-4\">\n            <div>\n              <p class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                Available Points Balance\n              </p>\n              <div class=\"mt-1 flex items-baseline gap-2\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums sm:text-4xl\"> 2,450 </span>\n                <span class=\"text-muted-foreground text-sm font-medium\">Points</span>\n              </div>\n            </div>\n            <p class=\"text-muted-foreground mt-3 text-xs font-medium\">\n              Estimated reward cash value:\n              <span class=\"text-success text-success font-semibold tabular-nums\">$24.50 reward value</span>\n            </p>\n          </div>\n\n          <!-- Tier Multiplier Stat -->\n          <div class=\"border-border/60 bg-muted/30 flex flex-col justify-between rounded-xl border p-4\">\n            <div>\n              <p class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Current Multiplier</p>\n              <div class=\"mt-1 flex items-center gap-2\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums sm:text-4xl\"> 2x </span>\n                <Badge wrap variant=\"success\" class=\"gap-1 text-xs\">\n                  <Zap class=\"size-3\" aria-hidden=\"true\" />\n                  Active\n                </Badge>\n              </div>\n            </div>\n            <p class=\"text-muted-foreground mt-3 text-xs font-medium\">\n              Earn 2 points per $1 spent on all boutique catalog orders.\n            </p>\n          </div>\n\n          <!-- Next Reward Threshold -->\n          <div\n            class=\"border-border/60 bg-muted/30 flex flex-col justify-between rounded-xl border p-4 sm:col-span-2 lg:col-span-1\"\n          >\n            <div>\n              <p class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Next Tier Goal</p>\n              <div class=\"mt-1 flex items-baseline gap-2\">\n                <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums sm:text-3xl\">\n                  550 pts\n                </span>\n                <span class=\"text-muted-foreground text-xs font-medium\">to Diamond VIP</span>\n              </div>\n            </div>\n            <p class=\"text-muted-foreground mt-3 text-xs font-medium\">\n              Unlocks 3x points multiplier and annual exclusive gift.\n            </p>\n          </div>\n        </div>\n\n        <!-- Next Tier Progress Bar Section -->\n        <div class=\"border-border/80 bg-muted/40 space-y-2.5 rounded-xl border p-4\">\n          <div class=\"flex flex-wrap items-center justify-between gap-2 text-xs sm:text-sm\">\n            <div class=\"flex items-center gap-2\">\n              <Award class=\"text-primary size-4 shrink-0\" aria-hidden=\"true\" />\n              <span class=\"text-foreground font-semibold\">Next Tier Progress: Diamond VIP</span>\n            </div>\n            <span class=\"text-foreground font-semibold tabular-nums\">2,450 / 3,000 Points</span>\n          </div>\n\n          <Progress :model-value=\"81.6\" class=\"h-2.5\" />\n\n          <div class=\"flex flex-wrap items-center justify-between gap-2 text-xs\">\n            <span class=\"text-muted-foreground font-medium tabular-nums\">\n              81.6% to Diamond VIP · 550 points to upgrade\n            </span>\n            <span class=\"text-muted-foreground\"> Target qualification date: Dec 31, 2024 </span>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- 4 VIP Tier Privilege Perks Summary -->\n    <div class=\"space-y-3\">\n      <div class=\"flex items-center justify-between gap-2\">\n        <div>\n          <h3 class=\"text-foreground text-base font-semibold\">VIP Tier Privilege Perks</h3>\n          <p class=\"text-muted-foreground text-xs\">\n            Active benefits unlocked with your Platinum status and next-tier Diamond previews.\n          </p>\n        </div>\n        <Badge wrap variant=\"outline\" class=\"shrink-0 text-xs font-medium tabular-nums\"> 3 of 4 Perks Active </Badge>\n      </div>\n\n      <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n        <div\n          v-for=\"perk in perks\"\n          :key=\"perk.id\"\n          :class=\"\n            cn(\n              'flex flex-col justify-between rounded-xl border p-4 transition-colors',\n              perk.status === 'active'\n                ? 'border-border/80 bg-card shadow-xs'\n                : 'border-border/60 bg-muted/20 opacity-85',\n            )\n          \"\n        >\n          <div class=\"space-y-3\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div\n                :class=\"\n                  cn(\n                    'flex size-9 shrink-0 items-center justify-center rounded-lg border',\n                    perk.id === 'perk-shipping' && 'border-success/20 bg-success/10 text-success',\n                    perk.id === 'perk-archive' && 'border-chart-1/30 bg-chart-1/10 text-chart-1',\n                    perk.id === 'perk-stylist' && 'border-info/20 bg-info/10 text-info',\n                    perk.id === 'perk-annual-gift' && 'border-border/60 bg-muted text-muted-foreground',\n                  )\n                \"\n              >\n                <Truck v-if=\"perk.id === 'perk-shipping'\" class=\"size-4\" aria-hidden=\"true\" />\n                <Tag v-else-if=\"perk.id === 'perk-archive'\" class=\"size-4\" aria-hidden=\"true\" />\n                <Headphones v-else-if=\"perk.id === 'perk-stylist'\" class=\"size-4\" aria-hidden=\"true\" />\n                <Gift v-else class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n\n              <Badge v-if=\"perk.status === 'active'\" variant=\"success\" class=\"gap-1 text-xs whitespace-normal\">\n                <Check class=\"size-3\" aria-hidden=\"true\" />\n                Active\n              </Badge>\n              <Badge wrap v-else variant=\"secondary\" class=\"text-muted-foreground gap-1 text-xs\">\n                <Lock class=\"size-3\" aria-hidden=\"true\" />\n                Unlocks at 3,000 pts\n              </Badge>\n            </div>\n\n            <div>\n              <p class=\"text-foreground text-sm font-semibold\">{{ perk.title }}</p>\n              <p class=\"text-muted-foreground mt-0.5 text-xs font-medium\">{{ perk.subtitle }}</p>\n              <p class=\"text-muted-foreground mt-2 text-xs leading-relaxed\">\n                {{ perk.description }}\n              </p>\n            </div>\n          </div>\n\n          <div class=\"border-border/50 mt-4 border-t pt-3\">\n            <span class=\"text-muted-foreground text-xs\">\n              {{ perk.status === 'active' ? 'Included in Platinum VIP' : 'Requires Diamond Tier' }}\n            </span>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <!-- Rewards Catalog Grid (3 unlockable rewards) -->\n    <div class=\"space-y-3\">\n      <div class=\"flex items-center justify-between gap-2\">\n        <div>\n          <h3 class=\"text-foreground text-base font-semibold\">Rewards Catalog</h3>\n          <p class=\"text-muted-foreground text-xs\">\n            Redeem your points balance for instant discount vouchers and complimentary luxury items.\n          </p>\n        </div>\n        <Badge wrap variant=\"outline\" class=\"shrink-0 text-xs font-medium tabular-nums\"> 2 Available to Redeem </Badge>\n      </div>\n\n      <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n        <Card\n          v-for=\"reward in rewards\"\n          :key=\"reward.id\"\n          :class=\"\n            cn(\n              'border-border/80 flex flex-col justify-between shadow-xs transition-colors',\n              !reward.unlocked && 'bg-muted/20 opacity-90',\n            )\n          \"\n        >\n          <CardHeader class=\"pb-3\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <Badge wrap variant=\"secondary\" class=\"min-w-0 shrink text-xs font-medium\">\n                {{ reward.category }}\n              </Badge>\n              <div class=\"shrink-0 text-right\">\n                <span class=\"text-foreground text-sm font-bold tabular-nums\">\n                  {{ reward.pointsCost.toLocaleString() }} pts\n                </span>\n              </div>\n            </div>\n            <CardTitle class=\"mt-2 text-base font-semibold\">\n              {{ reward.title }}\n            </CardTitle>\n            <CardDescription class=\"text-xs leading-relaxed\">\n              {{ reward.description }}\n            </CardDescription>\n          </CardHeader>\n\n          <CardContent class=\"pb-3\">\n            <!-- When locked, show points shortfall -->\n            <div v-if=\"!reward.unlocked\" class=\"space-y-1.5\">\n              <div class=\"flex items-center justify-between text-xs\">\n                <span class=\"text-muted-foreground\">Progress to unlock</span>\n                <span class=\"text-foreground font-semibold tabular-nums\">2,450 / 3,000 pts</span>\n              </div>\n              <Progress :model-value=\"81.6\" class=\"h-1.5\" />\n            </div>\n\n            <!-- When redeemed, show code -->\n            <div\n              v-else-if=\"redeemedMap[reward.id]\"\n              class=\"border-success/30 bg-success/10 text-success rounded-md border p-2.5 text-center text-xs font-medium\"\n            >\n              <div class=\"flex items-center justify-center gap-1\">\n                <Check class=\"size-3.5\" aria-hidden=\"true\" />\n                <span>Redeemed! Code:</span>\n                <span class=\"font-mono font-bold\">{{ reward.code }}</span>\n              </div>\n            </div>\n          </CardContent>\n\n          <CardFooter class=\"pt-0\">\n            <Button\n              v-if=\"reward.unlocked && !redeemedMap[reward.id]\"\n              type=\"button\"\n              class=\"w-full gap-1.5 text-xs font-medium\"\n              @click=\"handleRedeem(reward.id)\"\n            >\n              <Tag class=\"size-3.5\" aria-hidden=\"true\" />\n              <span>Redeem Reward</span>\n            </Button>\n\n            <Button\n              v-else-if=\"reward.unlocked && redeemedMap[reward.id]\"\n              type=\"button\"\n              variant=\"outline\"\n              class=\"border-success/40 text-success w-full gap-1.5 text-xs font-medium\"\n              disabled\n            >\n              <Check class=\"size-3.5\" aria-hidden=\"true\" />\n              <span>Voucher Claimed</span>\n            </Button>\n\n            <Button v-else type=\"button\" variant=\"outline\" disabled class=\"w-full gap-1.5 text-xs font-medium\">\n              <Lock class=\"size-3.5\" aria-hidden=\"true\" />\n              <span>Locked · Need {{ reward.pointsNeeded }} pts</span>\n            </Button>\n          </CardFooter>\n        </Card>\n      </div>\n    </div>\n\n    <!-- Points History Ledger -->\n    <Card class=\"border-border/80 shadow-xs\">\n      <CardHeader class=\"pb-4\">\n        <div class=\"flex items-center justify-between gap-2\">\n          <div>\n            <div class=\"flex items-center gap-2\">\n              <History class=\"text-muted-foreground size-4\" aria-hidden=\"true\" />\n              <CardTitle class=\"text-base font-semibold\">Points History Ledger</CardTitle>\n            </div>\n            <CardDescription> Recent earnings and redemption transactions on your VIP account. </CardDescription>\n          </div>\n          <Badge wrap variant=\"outline\" class=\"shrink-0 text-xs font-medium tabular-nums\">\n            Recent 4 Transactions\n          </Badge>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"p-0 sm:p-6 sm:pt-0\">\n        <div class=\"overflow-x-auto\">\n          <Table density=\"cozy\">\n            <TableHeader>\n              <TableRow>\n                <TableHead>Transaction Details</TableHead>\n                <TableHead>Type &amp; Multiplier</TableHead>\n                <TableHead>Date</TableHead>\n                <TableHead class=\"text-right\">Points Change</TableHead>\n              </TableRow>\n            </TableHeader>\n            <TableBody>\n              <TableRow v-for=\"tx in ledgerTransactions\" :key=\"tx.id\">\n                <TableCell>\n                  <div class=\"flex items-center gap-3\">\n                    <div\n                      :class=\"\n                        cn(\n                          'flex size-8 shrink-0 items-center justify-center rounded-lg border',\n                          tx.isPositive\n                            ? 'border-success/20 bg-success/10 text-success'\n                            : 'border-border/60 bg-muted text-muted-foreground',\n                        )\n                      \"\n                    >\n                      <ShoppingBag v-if=\"tx.isPositive && tx.pointsChange < 500\" class=\"size-4\" aria-hidden=\"true\" />\n                      <Crown v-else-if=\"tx.isPositive && tx.pointsChange >= 500\" class=\"size-4\" aria-hidden=\"true\" />\n                      <Ticket v-else class=\"size-4\" aria-hidden=\"true\" />\n                    </div>\n                    <div class=\"min-w-0\">\n                      <p class=\"text-foreground truncate text-sm font-medium\">\n                        {{ tx.title }}\n                      </p>\n                      <p class=\"text-muted-foreground truncate text-xs\">\n                        {{ tx.subtitle }}\n                      </p>\n                    </div>\n                  </div>\n                </TableCell>\n                <TableCell>\n                  <Badge\n                    v-if=\"tx.type.includes('Multiplier')\"\n                    variant=\"outline\"\n                    class=\"gap-1 text-xs font-medium whitespace-normal\"\n                  >\n                    <Zap class=\"text-warning size-3\" aria-hidden=\"true\" />\n                    {{ tx.type }}\n                  </Badge>\n                  <Badge\n                    v-else-if=\"tx.type.includes('Milestone')\"\n                    variant=\"outline\"\n                    class=\"border-primary/20 bg-primary/10 text-primary gap-1 text-xs font-medium whitespace-normal\"\n                  >\n                    <Crown class=\"text-primary size-3\" aria-hidden=\"true\" />\n                    {{ tx.type }}\n                  </Badge>\n                  <Badge wrap v-else variant=\"secondary\" class=\"text-muted-foreground gap-1 text-xs font-medium\">\n                    <Ticket class=\"size-3\" aria-hidden=\"true\" />\n                    {{ tx.type }}\n                  </Badge>\n                </TableCell>\n                <TableCell class=\"text-muted-foreground text-xs whitespace-nowrap sm:text-sm\">\n                  {{ tx.date }}\n                </TableCell>\n                <TableCell class=\"text-right text-xs font-medium tabular-nums sm:text-sm\">\n                  <span :class=\"tx.isPositive ? 'text-success font-bold' : 'text-muted-foreground font-semibold'\">\n                    {{\n                      tx.isPositive\n                        ? `+${tx.pointsChange.toLocaleString()} pts`\n                        : `${tx.pointsChange.toLocaleString()} pts`\n                    }}\n                  </span>\n                </TableCell>\n              </TableRow>\n            </TableBody>\n          </Table>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/LoyaltyRewardsTierHub.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "Sephora and Starbucks style VIP customer loyalty tier dashboard, points wallet, and rewards catalog. Features a customer hero card with points balance, reward valuation, and tier progress tracker, 4 VIP privilege perks with unlock statuses, a 3-item redeemable rewards catalog grid, and a recent points earnings & redemption history ledger.",
  "categories": [
    "commerce",
    "ecommerce",
    "dashboard",
    "marketing"
  ]
}