Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(CustomerRevamp): Refactor customer subscription list, customer coupons and customer details #1997

Merged
merged 64 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
bf6d50f
feat(icons): add arrow-indent icon
stephenlago99 Jan 21, 2025
fc75f47
chore(translations): add translations
stephenlago99 Jan 21, 2025
527dbb9
chore(graphql): generate types
stephenlago99 Jan 21, 2025
1c3f0e5
feat(TimezoneDate): add className prop
stephenlago99 Jan 21, 2025
7878a33
feat(Status): add support for downgrade and scheduled statuses
stephenlago99 Jan 21, 2025
61ab021
feat(icons): add arrow-indent icon
stephenlago99 Jan 21, 2025
2130fcd
feat(layoutsSection): create reusable page title component
stephenlago99 Jan 21, 2025
3eecbd6
feat(CouponCaption): add className prop
stephenlago99 Jan 21, 2025
a399066
refactor(CustomerPage): unify section heights
stephenlago99 Jan 21, 2025
351c17d
refactor(CustomerCoupons): list -> table
stephenlago99 Jan 21, 2025
74ef626
refactor(CustomerSubscriptionsList): list -> table
stephenlago99 Jan 21, 2025
614a6d0
refactor(CustomerMainInfos): always show all the customer details
stephenlago99 Jan 21, 2025
2113d66
refactor(CustomerOverview): re-use PageSectionTitle
stephenlago99 Jan 21, 2025
7e8f462
refactor(CustomerDetails): replace customer details drawer with tab
stephenlago99 Jan 21, 2025
9e1f2d7
fix: linting
stephenlago99 Jan 21, 2025
3fff010
fix(translations): remove unused translations
stephenlago99 Jan 22, 2025
414d064
feat(translations): add other languages
stephenlago99 Jan 22, 2025
5ca075f
refactor(Chip): remove clsx dependency
stephenlago99 Jan 22, 2025
13b23bb
refactor(CustomerSubscriptionsList): remove unused fragment
stephenlago99 Jan 22, 2025
4516e2b
fix(Status): fix types
stephenlago99 Jan 22, 2025
540e48f
refactor(CustomerSubscriptionsList): add padding to rows
stephenlago99 Jan 22, 2025
264948f
delete: remove SubscriptionLine
stephenlago99 Jan 22, 2025
6c55225
refactor(CustomerSubscriptionsList): update graphql
stephenlago99 Jan 22, 2025
9aa0a01
chore(graphql): generate types
stephenlago99 Jan 22, 2025
ab41ac7
refactor(CustomerSubscriptionsList): update fragment for next subscri…
stephenlago99 Jan 22, 2025
3ab4f5f
chore(translations): add translations
stephenlago99 Jan 23, 2025
129dfae
feat(CustomerDetails): update label
stephenlago99 Jan 23, 2025
0f4adff
feat(TimezoneDate): add typographyClassName prop
stephenlago99 Jan 23, 2025
1f1449b
refactor(CustomerSubscriptionsList): scheduled status. column order. …
stephenlago99 Jan 23, 2025
0877a93
chore(graphql): generate types
stephenlago99 Jan 23, 2025
9ddf7a9
fix(CustomerSubscriptionList): enable clicking on downgrade. fix down…
stephenlago99 Jan 23, 2025
237524f
fix: add table paddings
stephenlago99 Jan 23, 2025
50afb38
fix(CustomerSubscriptionList): pass subscription status to terminate …
stephenlago99 Jan 23, 2025
df2d487
feat: move customer overview to the invoices tab
stephenlago99 Jan 23, 2025
e57f62f
chore(translations): add translations
stephenlago99 Jan 23, 2025
60c16e9
feat(PageSectionTitle): add support for a custom action
stephenlago99 Jan 23, 2025
e3ec3b1
refactor(CustomerWalletsList): unify title
stephenlago99 Jan 23, 2025
0386de6
refactor(CustomerUsage): unify title
stephenlago99 Jan 23, 2025
00b78d5
refactor(CustomerOverview): add subtitle
stephenlago99 Jan 23, 2025
fcd0c1e
refactor(CustomerInvoicesTab): improve logic clarity. unify design
stephenlago99 Jan 23, 2025
6b05088
refactor(Settings): update spacing
stephenlago99 Jan 23, 2025
b93b176
chore(translations): add translations
stephenlago99 Jan 23, 2025
476b58f
refactor(CustomerInvoicesTab): do not show overview for 0 invoices. i…
stephenlago99 Jan 23, 2025
4467bd2
feat(tailwind): add first-child helper
stephenlago99 Jan 26, 2025
7d9ba54
chore(translations): add translations
stephenlago99 Jan 26, 2025
d85807a
refactor(CustomerMainInfos): separate into sections
stephenlago99 Jan 26, 2025
2b188da
refactor(CustomerMainInfos): render metadata and connections conditio…
stephenlago99 Jan 26, 2025
3c6d145
refactor(CustomerMainInfos): do not render border for last element
stephenlago99 Jan 26, 2025
a682fe5
chore(translations): add translations
stephenlago99 Jan 26, 2025
f4dba15
feat(CreditNotesTable): add filtersContainerClassName prop
stephenlago99 Jan 26, 2025
3a5147d
fix(CustomerCreditNotesList): remove legacy ScrollContainer
stephenlago99 Jan 26, 2025
9095a02
refactor(CreditNotesTable): remove legacy onKeyDown
stephenlago99 Jan 26, 2025
ae53e95
refactor(CustomerCreditNotesList): remove unused import
stephenlago99 Jan 26, 2025
52c09f2
fix(e2e): add missing data-test attributes
stephenlago99 Jan 26, 2025
4927823
fix(CustomerSettings): remove bottom padding
stephenlago99 Jan 27, 2025
9b5d947
chore(translations): update translations
stephenlago99 Jan 28, 2025
eea658c
fix(CustomerMainInfos): render billing information conditionally
stephenlago99 Jan 28, 2025
37389f9
chore(translations): update translations
stephenlago99 Jan 28, 2025
ffe8734
fix(navigation): navigate to information tab after save
stephenlago99 Jan 28, 2025
c959711
refactor(overdueBalance): refresh from card
stephenlago99 Jan 28, 2025
4163298
refactor(useCreateEditCustomer): redirect to overview
stephenlago99 Jan 28, 2025
9636f1d
refactor(loadingState): improve loading state
stephenlago99 Jan 28, 2025
0899311
refactor(CustomerInvoicesTab): loading state
stephenlago99 Jan 28, 2025
efad5d7
fix(translations): remove unused translations
stephenlago99 Jan 28, 2025
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
27 changes: 19 additions & 8 deletions src/components/OverviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface OverviewCardProps {
caption: string
isAccentContent?: boolean
isLoading?: boolean
refresh?: () => void
}

export const OverviewCard: FC<OverviewCardProps> = ({
Expand All @@ -18,26 +19,36 @@ export const OverviewCard: FC<OverviewCardProps> = ({
caption,
isAccentContent,
isLoading,
refresh,
}) => {
return (
<Card className="flex-1 gap-4 p-6">
{isLoading ? (
<div className="h-22">
<Skeleton className="mb-8 w-22" variant="text" />
<Skeleton className="w-22" variant="text" />
<div className="flex flex-col gap-4">
<Skeleton className="w-50" variant="text" />
<Skeleton className="w-12" variant="text" />
</div>
</div>
) : (
<>
<div className="flex items-center gap-2">
<Typography variant="captionHl">{title}</Typography>
{tooltipContent && (
<Tooltip className="flex h-5 items-end" placement="top-start" title={tooltipContent}>
<Icon name="info-circle" />
</Tooltip>
)}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Typography variant="captionHl">{title}</Typography>

{tooltipContent && (
<Tooltip
className="flex h-5 items-end"
placement="top-start"
title={tooltipContent}
>
<Icon name="info-circle" />
</Tooltip>
)}
</div>

{refresh && <Icon name="reload" onClick={refresh} />}
</div>

<div className="flex flex-col gap-1">
Expand Down
7 changes: 5 additions & 2 deletions src/components/TimezoneDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { TimezoneEnum } from '~/generated/graphql'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { useOrganizationInfos } from '~/hooks/useOrganizationInfos'
import { tw } from '~/styles/utils'

enum MainTimezoneEnum {
utc0 = 'utc0',
Expand All @@ -15,8 +16,9 @@
mainDateFormat?: string
mainTimezone?: keyof typeof MainTimezoneEnum
customerTimezone?: TimezoneEnum
mainTypographyProps?: Pick<TypographyProps, 'variant' | 'color'>
mainTypographyProps?: Pick<TypographyProps, 'variant' | 'color' | 'className'>
className?: string
typographyClassName?: string
}

export const TimezoneDate = ({
Expand All @@ -25,6 +27,7 @@
mainTimezone = MainTimezoneEnum.organization,
customerTimezone,
mainTypographyProps,
typographyClassName,
className,
}: TimezoneDateProps) => {
const { translate } = useInternationalization()
Expand Down Expand Up @@ -69,14 +72,14 @@
placement="top-end"
>
<Typography
className="w-max border-b-2 border-dotted border-grey-400"
className={tw('w-max border-b-2 border-dotted border-grey-400', typographyClassName)}
color="grey700"
{...mainTypographyProps}
noWrap
>
{formatDateToTZ(
date,
mainTimezone === MainTimezoneEnum.organization

Check warning on line 82 in src/components/TimezoneDate.tsx

View workflow job for this annotation

GitHub Actions / Run linters

Do not nest ternary expressions
? timezone
: mainTimezone === MainTimezoneEnum.customer
? customerTimezone
Expand Down
187 changes: 103 additions & 84 deletions src/components/coupons/CouponCaption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,104 +44,123 @@ export interface CouponMixedType extends CouponItemFragment {
interface CouponCaptionProps {
coupon: CouponMixedType
variant?: TypographyProps['variant']
className?: string
}

export const CouponCaption = memo(({ coupon, variant = 'caption' }: CouponCaptionProps) => {
const { translate } = useInternationalization()
export const CouponCaption = memo(
({ coupon, variant = 'caption', className }: CouponCaptionProps) => {
const { translate } = useInternationalization()

const getCaption = () => {
const {
amountCurrency,
amountCents,
amountCentsRemaining,
percentageRate,
frequency,
frequencyDuration,
frequencyDurationRemaining,
} = coupon
const couponType = amountCents ? CouponTypeEnum.FixedAmount : CouponTypeEnum.Percentage
const getCaption = () => {
const {
amountCurrency,
amountCents,
amountCentsRemaining,
percentageRate,
frequency,
frequencyDuration,
frequencyDurationRemaining,
} = coupon
const couponType = amountCents ? CouponTypeEnum.FixedAmount : CouponTypeEnum.Percentage

if (couponType === CouponTypeEnum.FixedAmount && frequency === CouponFrequency.Once) {
return translate(
amountCentsRemaining ? 'text_637b4da08cd0118cd0c4486f' : 'text_632d68358f1fedc68eed3e70',
{
amount: intlFormatNumber(
deserializeAmount(
Number(amountCentsRemaining) || Number(amountCents),
amountCurrency || CurrencyEnum.Usd,
) || 0,
{
currencyDisplay: 'symbol',
currency: amountCurrency || undefined,
},
),
},
)
} else if (couponType === CouponTypeEnum.Percentage && frequency === CouponFrequency.Once) {
return translate('text_632d68358f1fedc68eed3eb5', {
rate: intlFormatNumber(Number(percentageRate) / 100 || 0, {
style: 'percent',
}),
})
} else if (
couponType === CouponTypeEnum.FixedAmount &&
frequency === CouponFrequency.Recurring
) {
return translate(
'text_632d68358f1fedc68eed3ede',
{
if (couponType === CouponTypeEnum.FixedAmount && frequency === CouponFrequency.Once) {
return translate(
amountCentsRemaining ? 'text_637b4da08cd0118cd0c4486f' : 'text_632d68358f1fedc68eed3e70',
{
amount: intlFormatNumber(
deserializeAmount(
Number(amountCentsRemaining) || Number(amountCents),
amountCurrency || CurrencyEnum.Usd,
) || 0,
{
currencyDisplay: 'symbol',
currency: amountCurrency || undefined,
},
),
},
)
} else if (couponType === CouponTypeEnum.Percentage && frequency === CouponFrequency.Once) {
return translate('text_632d68358f1fedc68eed3eb5', {
rate: intlFormatNumber(Number(percentageRate) / 100 || 0, {
style: 'percent',
}),
})
} else if (
couponType === CouponTypeEnum.FixedAmount &&
frequency === CouponFrequency.Recurring
) {
return translate(
'text_632d68358f1fedc68eed3ede',
{
amount: intlFormatNumber(
deserializeAmount(
Number(amountCentsRemaining) || Number(amountCents),
amountCurrency || CurrencyEnum.Usd,
) || 0,
{
currencyDisplay: 'symbol',
currency: amountCurrency || undefined,
},
),
duration: frequencyDurationRemaining || frequencyDuration,
},
frequencyDurationRemaining || frequencyDuration || 1,
)
} else if (
couponType === CouponTypeEnum.Percentage &&
frequency === CouponFrequency.Recurring
) {
return translate(
'text_632d68358f1fedc68eed3ef9',
{
rate: intlFormatNumber(Number(percentageRate) / 100 || 0, {
style: 'percent',
}),
duration: frequencyDurationRemaining || frequencyDuration,
},
frequencyDurationRemaining || frequencyDuration || 1,
)
} else if (
couponType === CouponTypeEnum.FixedAmount &&
frequency === CouponFrequency.Forever
) {
return translate('text_63c946e8bef768ead2fee35c', {
amount: intlFormatNumber(
deserializeAmount(
Number(amountCentsRemaining) || Number(amountCents),
amountCurrency || CurrencyEnum.Usd,
) || 0,
deserializeAmount(Number(amountCents), amountCurrency || CurrencyEnum.Usd) || 0,
{
currencyDisplay: 'symbol',
currency: amountCurrency || undefined,
},
),
duration: frequencyDurationRemaining || frequencyDuration,
},
frequencyDurationRemaining || frequencyDuration || 1,
)
} else if (
couponType === CouponTypeEnum.Percentage &&
frequency === CouponFrequency.Recurring
) {
return translate(
'text_632d68358f1fedc68eed3ef9',
{
})
} else if (
couponType === CouponTypeEnum.Percentage &&
frequency === CouponFrequency.Forever
) {
return translate('text_63c96b18bfbf40e9ef600e99', {
rate: intlFormatNumber(Number(percentageRate) / 100 || 0, {
style: 'percent',
}),
duration: frequencyDurationRemaining || frequencyDuration,
},
frequencyDurationRemaining || frequencyDuration || 1,
)
} else if (couponType === CouponTypeEnum.FixedAmount && frequency === CouponFrequency.Forever) {
return translate('text_63c946e8bef768ead2fee35c', {
amount: intlFormatNumber(
deserializeAmount(Number(amountCents), amountCurrency || CurrencyEnum.Usd) || 0,
{
currencyDisplay: 'symbol',
currency: amountCurrency || undefined,
},
),
})
} else if (couponType === CouponTypeEnum.Percentage && frequency === CouponFrequency.Forever) {
return translate('text_63c96b18bfbf40e9ef600e99', {
rate: intlFormatNumber(Number(percentageRate) / 100 || 0, {
style: 'percent',
}),
})
})
}
}
}

return (
<Typography variant={variant} color="grey600" noWrap data-test="coupon-caption">
{getCaption()}
</Typography>
)
})
return (
<>
{!className && (
<Typography variant={variant} color="grey600" noWrap data-test="coupon-caption">
{getCaption()}
</Typography>
)}

{className && (
stephenlago99 marked this conversation as resolved.
Show resolved Hide resolved
<Typography className={className} data-test="coupon-caption">
{getCaption()}
</Typography>
)}
</>
)
},
)

CouponCaption.displayName = 'CouponCaption'
Loading
Loading