Details.tsx
9 months ago
icons.tsx
9 months ago
index.tsx
9 months ago
styles.module.scss
9 months ago
index.tsx
119 lines
| 1 | import { useState } from "react"; |
| 2 | import { __ } from "@wordpress/i18n"; |
| 3 | import classnames from 'classnames'; |
| 4 | import SyncDetails,{ SyncPaymentDetails } from "./Details"; |
| 5 | import { SubscriptionSyncResponse } from "../../../hooks/useSubscriptionSync"; |
| 6 | import styles from './styles.module.scss'; |
| 7 | |
| 8 | /** |
| 9 | * @since 4.8.0 |
| 10 | */ |
| 11 | type SubscriptionSyncListProps = { |
| 12 | syncResult: SubscriptionSyncResponse; |
| 13 | } |
| 14 | |
| 15 | /** |
| 16 | * @since 4.8.0 |
| 17 | */ |
| 18 | export default function SubscriptionSyncList({ syncResult }: SubscriptionSyncListProps) { |
| 19 | const { details, missingTransactions } = syncResult; |
| 20 | const [openItem, setOpenItem] = useState<string | null>(null); |
| 21 | |
| 22 | const statusUpdated = details?.currentStatus !== details?.gatewayStatus; |
| 23 | const periodUpdated = details?.currentPeriod !== details?.gatewayPeriod; |
| 24 | const createdAtUpdated = details?.currentCreatedAt !== details?.gatewayCreatedAt; |
| 25 | const paymentsUpdated = missingTransactions?.length > 0; |
| 26 | const transactions = paymentsUpdated ? missingTransactions : [null]; |
| 27 | |
| 28 | const handleItemToggle = (itemId: string) => { |
| 29 | setOpenItem(openItem === itemId ? null : itemId); |
| 30 | }; |
| 31 | |
| 32 | return ( |
| 33 | <div className={styles.list}> |
| 34 | <SyncItem |
| 35 | id="status" |
| 36 | title="Subscription status" |
| 37 | isAccurate={!statusUpdated} |
| 38 | isOpen={openItem === "status"} |
| 39 | onToggle={() => handleItemToggle("status")} |
| 40 | > |
| 41 | <SyncDetails isAccurate={!statusUpdated} platform={details?.currentStatus} gateway={details?.gatewayStatus} /> |
| 42 | </SyncItem> |
| 43 | <SyncItem |
| 44 | id="period" |
| 45 | title="Billing period" |
| 46 | isAccurate={!periodUpdated} |
| 47 | isOpen={openItem === "period"} |
| 48 | onToggle={() => handleItemToggle("period")} |
| 49 | > |
| 50 | <SyncDetails isAccurate={!periodUpdated} platform={details?.currentPeriod} gateway={details?.gatewayPeriod} /> |
| 51 | </SyncItem> |
| 52 | <SyncItem |
| 53 | id="created" |
| 54 | title="Date created" |
| 55 | isAccurate={!createdAtUpdated} |
| 56 | isOpen={openItem === "created"} |
| 57 | onToggle={() => handleItemToggle("created")} |
| 58 | > |
| 59 | <SyncDetails isAccurate={!createdAtUpdated} platform={details?.currentCreatedAt} gateway={details?.gatewayCreatedAt} /> |
| 60 | </SyncItem> |
| 61 | <SyncItem |
| 62 | id="payments" |
| 63 | title="Subscription payments" |
| 64 | isAccurate={!paymentsUpdated} |
| 65 | isOpen={openItem === "payments"} |
| 66 | onToggle={() => handleItemToggle("payments")} |
| 67 | > |
| 68 | {transactions?.map((transaction, index) => (<SyncPaymentDetails key={transaction?.id ?? `sync-payment-${index}`} isAccurate={!paymentsUpdated} payment={transaction} />))} |
| 69 | </SyncItem> |
| 70 | </div> |
| 71 | ); |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * @since 4.8.0 |
| 76 | */ |
| 77 | type SyncItemProps = { |
| 78 | id: string; |
| 79 | title: string; |
| 80 | isAccurate: boolean | null; |
| 81 | isOpen: boolean; |
| 82 | onToggle: () => void; |
| 83 | children: React.ReactNode; |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * @since 4.8.0 |
| 88 | */ |
| 89 | function SyncItem({ id, title, isAccurate, isOpen, onToggle, children }: SyncItemProps) { |
| 90 | return ( |
| 91 | <div id={id} className={styles.item}> |
| 92 | <div className={styles.itemContent}> |
| 93 | <div className={styles.itemHeader}> |
| 94 | <div> |
| 95 | <span |
| 96 | className={classnames(styles.itemPill, { |
| 97 | [styles.itemAccurate]: isAccurate, |
| 98 | })} |
| 99 | role="status" |
| 100 | aria-label={isAccurate ? __('ACCURATE', 'give') : __('UPDATED', 'give')} |
| 101 | > |
| 102 | {isAccurate ? __('ACCURATE', 'give') : __('UPDATED', 'give')} |
| 103 | </span> |
| 104 | <h2 className={styles.itemTitle}>{title}</h2> |
| 105 | </div> |
| 106 | <button |
| 107 | className={styles.itemButton} |
| 108 | onClick={onToggle} |
| 109 | > |
| 110 | {isOpen ? __('Close', 'give') : __('View details', 'give')} |
| 111 | </button> |
| 112 | </div> |
| 113 | |
| 114 | {isOpen && children} |
| 115 | </div> |
| 116 | </div> |
| 117 | ); |
| 118 | } |
| 119 |