Add customize-screen shop preview and purchase flow.
Locked items can be previewed on the pet from the editor, purchased with points in the preview modal, and opened in the full customize view from the shop.
This commit is contained in:
@@ -13,6 +13,7 @@ type RoomBackgroundPickerProps = {
|
||||
value: RoomBackgroundId;
|
||||
ownedItemIds: string[];
|
||||
onChange: (roomId: RoomBackgroundId) => void;
|
||||
onLockedSelect?: (roomId: RoomBackgroundId) => void;
|
||||
compact?: boolean;
|
||||
};
|
||||
|
||||
@@ -20,6 +21,7 @@ export function RoomBackgroundPicker({
|
||||
value,
|
||||
ownedItemIds,
|
||||
onChange,
|
||||
onLockedSelect,
|
||||
compact = false,
|
||||
}: RoomBackgroundPickerProps) {
|
||||
return (
|
||||
@@ -47,14 +49,20 @@ export function RoomBackgroundPicker({
|
||||
<button
|
||||
key={room.id}
|
||||
type="button"
|
||||
disabled={!unlocked}
|
||||
aria-pressed={selected}
|
||||
title={
|
||||
unlocked
|
||||
? room.name
|
||||
: `${room.name} — unlock in the shop`
|
||||
: `${room.name} — preview in shop`
|
||||
}
|
||||
onClick={() => onChange(room.id)}
|
||||
onClick={() => {
|
||||
if (!unlocked) {
|
||||
onLockedSelect?.(room.id);
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(room.id);
|
||||
}}
|
||||
className={cn(
|
||||
"relative aspect-[4/3] overflow-hidden border-2 transition-transform",
|
||||
selected
|
||||
@@ -62,7 +70,7 @@ export function RoomBackgroundPicker({
|
||||
: "border-border/70",
|
||||
unlocked
|
||||
? "hover:-translate-y-0.5"
|
||||
: "cursor-not-allowed opacity-80",
|
||||
: "opacity-80 hover:-translate-y-0.5",
|
||||
)}
|
||||
>
|
||||
<div className={cn("absolute inset-0", room.previewClassName)} />
|
||||
|
||||
@@ -14,12 +14,14 @@ type RoomStyleSelectorProps = {
|
||||
activeId: RoomBackgroundId;
|
||||
ownedItemIds: readonly string[];
|
||||
onSelect: (roomId: RoomBackgroundId) => void;
|
||||
onLockedSelect?: (roomId: RoomBackgroundId) => void;
|
||||
};
|
||||
|
||||
export function RoomStyleSelector({
|
||||
activeId,
|
||||
ownedItemIds,
|
||||
onSelect,
|
||||
onLockedSelect,
|
||||
}: RoomStyleSelectorProps) {
|
||||
const slots = Array.from({ length: PIECE_SLOT_COUNT }, (_, index) =>
|
||||
ROOM_BACKGROUNDS[index] ?? null,
|
||||
@@ -44,20 +46,25 @@ export function RoomStyleSelector({
|
||||
<button
|
||||
key={room.id}
|
||||
type="button"
|
||||
disabled={locked}
|
||||
aria-disabled={locked}
|
||||
title={
|
||||
locked ? `${room.name} — unlock in the shop` : room.name
|
||||
locked ? `${room.name} — preview in shop` : room.name
|
||||
}
|
||||
aria-label={
|
||||
locked ? `${room.name}, locked — unlock in the shop` : room.name
|
||||
locked ? `${room.name}, locked — preview to unlock` : room.name
|
||||
}
|
||||
aria-pressed={activeId === room.id}
|
||||
onClick={() => onSelect(room.id)}
|
||||
onClick={() => {
|
||||
if (locked) {
|
||||
onLockedSelect?.(room.id);
|
||||
return;
|
||||
}
|
||||
|
||||
onSelect(room.id);
|
||||
}}
|
||||
className={cn(
|
||||
"relative size-14 overflow-hidden rounded-lg border transition-colors",
|
||||
locked
|
||||
? "cursor-not-allowed border-border/40 opacity-80"
|
||||
? "border-border/40 opacity-80 hover:border-border"
|
||||
: activeId === room.id
|
||||
? "border-foreground shadow-[inset_0_0_0_1px_hsl(var(--foreground)/0.15)]"
|
||||
: "border-border/60 hover:border-border",
|
||||
|
||||
Reference in New Issue
Block a user