fix(tip): refine gift presentation
This commit is contained in:
@@ -57,4 +57,36 @@ describe("tip screen helpers", () => {
|
||||
),
|
||||
).toEqual([TIP_GIFT_PLACEHOLDER_IMAGE]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["coffee_small", "/images/tip/small.jpg"],
|
||||
["coffee_medium", "/images/tip/medium.png"],
|
||||
["coffee_large", "/images/tip/large.png"],
|
||||
])("uses the %s tier image as its local fallback", (tipType, expected) => {
|
||||
const tierProduct = GiftProductSchema.parse({
|
||||
...product,
|
||||
tipType,
|
||||
imageUrl: null,
|
||||
});
|
||||
const categoryWithoutImage = GiftCategorySchema.parse({
|
||||
...category,
|
||||
imageUrl: null,
|
||||
});
|
||||
|
||||
expect(getGiftImageSources(tierProduct, categoryWithoutImage)).toEqual([
|
||||
expected,
|
||||
]);
|
||||
});
|
||||
|
||||
it("uses the generic placeholder for unknown gift types", () => {
|
||||
const unknownProduct = GiftProductSchema.parse({
|
||||
...product,
|
||||
tipType: "flowers",
|
||||
imageUrl: null,
|
||||
});
|
||||
|
||||
expect(getGiftImageSources(unknownProduct, null)).toEqual([
|
||||
TIP_GIFT_PLACEHOLDER_IMAGE,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,11 +43,6 @@ export function TipGiftProductSelector({
|
||||
/>
|
||||
<span className={styles.tierDetails}>
|
||||
<span className={styles.tierName}>{product.planName}</span>
|
||||
{product.description ? (
|
||||
<span className={styles.tierDescription}>
|
||||
{product.description}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
<span className={styles.tierPriceBlock}>
|
||||
<span className={styles.tierPrice}>
|
||||
|
||||
@@ -5,6 +5,12 @@ import type {
|
||||
|
||||
export const TIP_GIFT_PLACEHOLDER_IMAGE = "/images/tip/medium.png";
|
||||
|
||||
const TIP_GIFT_PLACEHOLDER_BY_TIP_TYPE: Readonly<Record<string, string>> = {
|
||||
coffee_small: "/images/tip/small.jpg",
|
||||
coffee_medium: "/images/tip/medium.png",
|
||||
coffee_large: "/images/tip/large.png",
|
||||
};
|
||||
|
||||
export function formatGiftPrice(
|
||||
amountCents: number,
|
||||
currency: string,
|
||||
@@ -25,10 +31,15 @@ export function getGiftImageSources(
|
||||
product: GiftProduct | null,
|
||||
category: GiftCategory | null,
|
||||
): readonly string[] {
|
||||
const placeholderImage = product
|
||||
? (TIP_GIFT_PLACEHOLDER_BY_TIP_TYPE[product.tipType] ??
|
||||
TIP_GIFT_PLACEHOLDER_IMAGE)
|
||||
: TIP_GIFT_PLACEHOLDER_IMAGE;
|
||||
|
||||
return [
|
||||
product?.imageUrl,
|
||||
category?.imageUrl,
|
||||
TIP_GIFT_PLACEHOLDER_IMAGE,
|
||||
placeholderImage,
|
||||
].filter(
|
||||
(source, index, sources): source is string =>
|
||||
Boolean(source) && sources.indexOf(source) === index,
|
||||
|
||||
@@ -226,14 +226,6 @@
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.productDescription {
|
||||
margin: 10px 0 0;
|
||||
color: #7d6264;
|
||||
font-size: clamp(12px, 3.148vw, 15px);
|
||||
font-weight: 620;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.visuallyHidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -352,17 +344,6 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tierDescription {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
color: #80676a;
|
||||
font-size: 11px;
|
||||
font-weight: 620;
|
||||
line-height: 1.35;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
.tierPriceBlock {
|
||||
align-items: flex-end;
|
||||
gap: 3px;
|
||||
|
||||
@@ -286,11 +286,6 @@ export function TipScreen({
|
||||
selectedProduct.currency,
|
||||
)}
|
||||
</p>
|
||||
{selectedProduct.description ? (
|
||||
<p className={styles.productDescription}>
|
||||
{selectedProduct.description}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<TipGiftProductSelector
|
||||
|
||||
@@ -102,7 +102,7 @@ export function TipSuccessView({
|
||||
className={styles.title}
|
||||
tabIndex={-1}
|
||||
>
|
||||
You made {characterName} smile.
|
||||
Thank you. Your gift made me smile.
|
||||
</h1>
|
||||
<div className={styles.copy}>
|
||||
<p>
|
||||
|
||||
Reference in New Issue
Block a user