Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/mint-components/.changeset/chatty-tools-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@saasquatch/mint-components": patch
---

display retracted referrals as cancelled
19 changes: 19 additions & 0 deletions packages/mint-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { QRCodeViewProps } from "./components/sqm-qr-code/sqm-qr-code-view";
import { ReferralCodesViewProps } from "./components/sqm-referral-codes/sqm-referral-codes-view";
import { ReferralIframeViewProps } from "./components/sqm-referral-iframe/sqm-referral-iframe-view";
import { ReferralDates } from "./components/sqm-referral-table/useReferralTable";
import { ReferralStatus } from "./components/sqm-referral-table/referralStatus";
import { RewardExchangeViewProps } from "./components/sqm-reward-exchange-list/sqm-reward-exchange-list-view";
import { ShareButtonViewProps } from "./components/sqm-share-button/sqm-share-button-view";
import { ShareLinkViewProps } from "./components/sqm-share-link/sqm-share-link-view";
Expand Down Expand Up @@ -4311,6 +4312,7 @@ export namespace Components {
interface SqmReferralTableStatusCell {
"converted": boolean;
"fraudStatus"?: FraudStatus;
"status"?: ReferralStatus;
"statusSubText": string;
"statusText": string;
}
Expand Down Expand Up @@ -4346,6 +4348,14 @@ export namespace Components {
"renderCell": (data: Referral) => Promise<any>;
"renderLabel": () => Promise<string>;
"renderReferrerCell": (data: Referrer) => Promise<any>;
/**
* @uiName Retracted status sub-text
*/
"retractedStatusSubText": string;
/**
* @uiName Retracted status text
*/
"retractedStatusText": string;
}
interface SqmReferralTableUserCell {
"name": string;
Expand Down Expand Up @@ -12793,6 +12803,7 @@ declare namespace LocalJSX {
interface SqmReferralTableStatusCell {
"converted"?: boolean;
"fraudStatus"?: FraudStatus;
"status"?: ReferralStatus;
"statusSubText"?: string;
"statusText"?: string;
}
Expand Down Expand Up @@ -12825,6 +12836,14 @@ declare namespace LocalJSX {
* @uiName Pending review status text
*/
"pendingReviewStatusText"?: string;
/**
* @uiName Retracted status sub-text
*/
"retractedStatusSubText"?: string;
/**
* @uiName Retracted status text
*/
"retractedStatusText"?: string;
}
interface SqmReferralTableUserCell {
"name"?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

## Properties

| Property | Attribute | Description | Type | Default |
| --------------------------- | ------------------------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `demoData` | -- | | `{ states?: { noCodes: boolean; loading: boolean; }; slots?: { shareButtons: VNode; shareCodes: VNode; pagination: VNode; empty: VNode; loading: VNode; }; titleText?: string; textColor?: string; }` | `undefined` |
| `emptyStateDescriptionText` | `empty-state-description-text` | | `string` | `"Please contact our program support team to let them know you’re out of codes."` |
| `emptyStateHeaderText` | `empty-state-header-text` | | `string` | `"Your new codes and links aren’t ready yet"` |
| `emptyStateImageUrl` | `empty-state-image-url` | | `string` | `"https://res.cloudinary.com/saasquatch/image/upload/v1644360953/squatch-assets/empty_leaderboard2.png"` |
| `programId` | `program-id` | | `string` | `undefined` |
| `textColor` | `text-color` | | `string` | `undefined` |
| `titleText` | `title-text` | | `string` | `"Start sharing"` |
| Property | Attribute | Description | Type | Default |
| --------------------------- | ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `demoData` | -- | | `{ states?: { noCodes: boolean; loading: boolean; }; slots?: { shareButtons: VNode; shareCodes: VNode; pagination: VNode; empty: VNode; }; titleText?: string; textColor?: string; }` | `undefined` |
| `emptyStateDescriptionText` | `empty-state-description-text` | | `string` | `"Please contact our program support team to let them know you’re out of codes."` |
| `emptyStateHeaderText` | `empty-state-header-text` | | `string` | `"Your new codes and links aren’t ready yet"` |
| `emptyStateImageUrl` | `empty-state-image-url` | | `string` | `"https://res.cloudinary.com/saasquatch/image/upload/v1644360953/squatch-assets/empty_leaderboard2.png"` |
| `programId` | `program-id` | | `string` | `undefined` |
| `textColor` | `text-color` | | `string` | `undefined` |
| `titleText` | `title-text` | | `string` | `"Start sharing"` |


## Dependencies
Expand All @@ -27,13 +27,11 @@
### Depends on

- [sqm-empty](../sqm-empty)
- [sqm-skeleton](../sqm-skeleton)

### Graph
```mermaid
graph TD;
sqm-referral-codes --> sqm-empty
sqm-referral-codes --> sqm-skeleton
sqm-empty --> sqm-portal-container
sqm-empty --> sqm-titled-section
sqm-empty --> sqm-text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,48 @@ export const EmptyCell = () => (

export const Converted = () => (
<sqm-referral-table-status-cell
status="CONVERTED"
status-text="Converted"
fraud-status="APPROVED"
converted={true}
></sqm-referral-table-status-cell>
);
export const InProgress = () => (
<sqm-referral-table-status-cell
status="IN_PROGRESS"
status-text="In Progress"
converted={false}
></sqm-referral-table-status-cell>
);
export const Retracted = () => (
<sqm-referral-table-status-cell
status="RETRACTED"
status-text="Cancelled"
status-sub-text="This purchase was cancelled or refunded"
converted={true}
></sqm-referral-table-status-cell>
);
export const PendingReview = () => (
<sqm-referral-table-status-cell
status="PENDING_REVIEW"
status-text="Pending"
fraud-status="PENDING_REVIEW"
status-sub-text="Awaiting review"
fraud-status="PENDING"
converted={false}
></sqm-referral-table-status-cell>
);
export const Pending = () => (
<sqm-referral-table-status-cell
status="PENDING_REVIEW"
status-text="Pending"
// fraud-status="PENDING_REVIEW"
converted={false}
></sqm-referral-table-status-cell>
);
export const Denied = () => (
<sqm-referral-table-status-cell
status="DENIED"
status-text="Denied"
status-sub-text="Detected self-referral"
fraud-status="DENIED"
converted={false}
></sqm-referral-table-status-cell>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { Component, h, Prop } from "@stencil/core";
import { FraudStatus } from "../../../saasquatch";
import { createStyleSheet } from "../../../styling/JSS";
import { ReferralStatus } from "../referralStatus";

type ShoeLaceBadgeType = "primary" | "danger" | "warning" | "success" | "info";

const badgeTypeMap: Record<ReferralStatus, ShoeLaceBadgeType> = {
DENIED: "danger",
RETRACTED: "danger",
PENDING_REVIEW: "warning",
CONVERTED: "success",
IN_PROGRESS: "warning",
};

const style = {
SubText: {
Expand Down Expand Up @@ -63,6 +74,7 @@ const styleString = sheet.toString();
})
export class ReferralTableStatusCell {
@Prop() statusText: string;
@Prop() status?: ReferralStatus;
@Prop() fraudStatus?: FraudStatus;
@Prop() converted: boolean;
@Prop() statusSubText: string;
Expand All @@ -71,21 +83,16 @@ export class ReferralTableStatusCell {
const sheet = createStyleSheet(style);
const styleString = sheet.toString();

const getBadgeType = (fraudStatus) => {
if (fraudStatus === "PENDING") return "warning";
if (fraudStatus === "DENIED") return "danger";
const getBadgeType = (): ShoeLaceBadgeType => {
if (this.status) return badgeTypeMap[this.status];

// Callers that predate the status prop still set fraudStatus/converted
if (this.fraudStatus === "PENDING") return "warning";
if (this.fraudStatus === "DENIED") return "danger";
if (this.converted) return "success";
return "warning";
};

type ShoeLaceBadgeType =
| "primary"
| "danger"
| "warning"
| "success"
| "info";

const getBadgeCSSClass = (badgeType: ShoeLaceBadgeType): string => {
switch (badgeType) {
case "primary":
Expand All @@ -111,8 +118,8 @@ export class ReferralTableStatusCell {
<style type="text/css">{styleString}</style>
<sl-badge
pill
type={getBadgeType(this.fraudStatus)}
class={getBadgeCSSClass(getBadgeType(this.fraudStatus))}
type={getBadgeType()}
class={getBadgeCSSClass(getBadgeType())}
>
{this.statusText}
</sl-badge>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,21 @@ Feature: Referral Table Status Column
| Converted | convertedStatusText | Green |
| Pending | pendingReviewStatusText | Orange |
| Denied | deniedStatusText | Red |
| Cancelled | retractedStatusText | Red |

@motivating
Scenario: A referral whose conversion was retracted is not shown as converted
Given a referral with both `dateConverted` and `dateConversionRetracted` set
Then the status is displayed as text from retractedStatusText in a Red pill
And the sub-text from retractedStatusSubText is displayed

@minutia
Scenario Outline: Fraud moderation takes precedence over the conversion state
Given a referral with `dateConverted` and `dateConversionRetracted` set
And the referral `fraudData.moderationStatus` is <moderationStatus>
Then the status is displayed as text from <statusTextProp>

Examples:
| moderationStatus | statusTextProp |
| "DENIED" | deniedStatusText |
| "PENDING" | pendingReviewStatusText |
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { withHooks } from "@saasquatch/stencil-hooks";
import { Component, h, Host, Method, Prop } from "@stencil/core";
import { FraudStatus, Referral, Referrer } from "../../../saasquatch";
import { Referral, Referrer } from "../../../saasquatch";
import { useRequestRerender } from "../../../tables/re-render";
import { getReferralStatus, ReferralStatus } from "../referralStatus";
import { ReferralTableColumn } from "./ReferralTableColumn";

/**
* @uiName Referral Table Status Column
* @validParents ["sqm-referral-table"]
* @exampleGroup Referrals
* @example Referral Table Status Column - <sqm-referral-table-status-column column-title="Status" converted-status-text="Converted" in-progress-status-text="In Progress" pending-review-status-text="Pending" denied-status-text="Denied" pending-review-status-sub-text="Awaiting review" denied-status-sub-text="Detected self-referral"></sqm-referral-table-status-column>
* @example Referral Table Status Column - <sqm-referral-table-status-column column-title="Status" converted-status-text="Converted" in-progress-status-text="In Progress" pending-review-status-text="Pending" denied-status-text="Denied" retracted-status-text="Cancelled" pending-review-status-sub-text="Awaiting review" denied-status-sub-text="Detected self-referral" retracted-status-sub-text="This purchase was cancelled or refunded"></sqm-referral-table-status-column>
*/
@Component({
tag: "sqm-referral-table-status-column",
Expand Down Expand Up @@ -40,6 +41,11 @@ export class ReferralTableStatusColumn implements ReferralTableColumn {
*/
@Prop() deniedStatusText: string = "Denied";

/**
* @uiName Retracted status text
*/
@Prop() retractedStatusText: string = "Cancelled";

/**
* @uiName Pending review status sub-text
*/
Expand All @@ -50,36 +56,50 @@ export class ReferralTableStatusColumn implements ReferralTableColumn {
*/
@Prop() deniedStatusSubText: string = "Detected self-referral";

/**
* @uiName Retracted status sub-text
*/
@Prop() retractedStatusSubText: string =
"This purchase was cancelled or refunded";

constructor() {
withHooks(this);
}
disconnectedCallback() {}

private getStatusCopy(status: ReferralStatus): {
text: string;
subText?: string;
} {
return {
DENIED: {
text: this.deniedStatusText,
subText: this.deniedStatusSubText,
},
PENDING_REVIEW: {
text: this.pendingReviewStatusText,
subText: this.pendingReviewStatusSubText,
},
RETRACTED: {
text: this.retractedStatusText,
subText: this.retractedStatusSubText,
},
CONVERTED: { text: this.convertedStatusText },
IN_PROGRESS: { text: this.inProgressStatusText },
}[status];
}

@Method()
async renderCell(data: Referral) {
// TODO: Make ICU and more complete
let statusText: string;
let statusSubText: string;

const fraudStatus: FraudStatus = data?.fraudData?.moderationStatus;

if (fraudStatus === "DENIED") {
statusText = this.deniedStatusText;
statusSubText = this.deniedStatusSubText;
} else if (fraudStatus === "PENDING") {
statusText = this.pendingReviewStatusText;
statusSubText = this.pendingReviewStatusSubText;
} else {
statusText = data.dateConverted
? this.convertedStatusText
: this.inProgressStatusText;
}
const status = getReferralStatus(data);
const { text, subText } = this.getStatusCopy(status);

return (
<sqm-referral-table-status-cell
status-text={statusText}
status-sub-text={statusSubText}
fraud-status={fraudStatus}
status={status}
status-text={text}
status-sub-text={subText}
fraud-status={data?.fraudData?.moderationStatus}
converted={data.dateConverted ? true : false}
></sqm-referral-table-status-cell>
);
Expand All @@ -92,13 +112,14 @@ export class ReferralTableStatusColumn implements ReferralTableColumn {

@Method()
async renderReferrerCell(data: Referrer) {
// TODO: Make ICU and more complete
const statusText = data.dateConverted
? this.convertedStatusText
: this.inProgressStatusText;
const status = getReferralStatus(data);
const { text, subText } = this.getStatusCopy(status);

return (
<sqm-referral-table-status-cell
status-text={statusText}
status={status}
status-text={text}
status-sub-text={subText}
converted={data.dateConverted ? true : false}
></sqm-referral-table-status-cell>
);
Expand All @@ -109,6 +130,12 @@ export class ReferralTableStatusColumn implements ReferralTableColumn {
this.columnTitle,
this.convertedStatusText,
this.inProgressStatusText,
this.pendingReviewStatusText,
this.deniedStatusText,
this.retractedStatusText,
this.pendingReviewStatusSubText,
this.deniedStatusSubText,
this.retractedStatusSubText,
]);
return <Host style={{ display: "none" }} />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const getMockData = () => {
Math.floor(Math.random() * 10) >= 5
? DateTime.now().minus({ days: 6 }).toMillis()
: null,
dateConversionRetracted: null,
dateFraudChecksCompleted: null,
dateModerated: 1558730033306,
dateModified: 1554934543447,
Expand Down
Loading
Loading