fix: replace card and small refactor

This commit is contained in:
Arman
2023-11-22 18:50:12 +01:00
parent 726d165036
commit d24d6aeb00
6 changed files with 247 additions and 186 deletions
+152
View File
@@ -0,0 +1,152 @@
<script lang="ts">
import { Alert } from '$lib/components';
import { onMount } from 'svelte';
import Form from '$lib/elements/forms/form.svelte';
import { trackEvent } from '$lib/actions/analytics';
import { clickOnEnter } from '$lib/helpers/a11y';
export let show = false;
export let size: 'small' | 'big' = 'big';
export let icon: string = null;
export let state: 'success' | 'warning' | 'error' | 'info' = null;
export let error: string = null;
export let closable = true;
export let headerDivider = true;
export let onSubmit: (e: SubmitEvent) => Promise<void> | void = function () {
return;
};
export let title = '';
export let description = '';
let backdrop: HTMLDivElement;
onMount(async () => {
document.body.appendChild(backdrop);
});
function handleBLur(event: MouseEvent) {
if (event.target === backdrop) {
trackEvent('click_close_modal', {
from: 'backdrop'
});
closeModal();
}
}
function closeModal() {
if (show) {
show = false;
document.documentElement.classList.remove('u-overflow-hidden');
}
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') {
event.preventDefault();
trackEvent('click_close_modal', {
from: 'escape'
});
closeModal();
}
}
$: if (show) {
document.documentElement.classList.add('u-overflow-hidden');
} else {
closeModal();
error = null;
}
</script>
<svelte:window on:keydown={handleKeydown} />
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="payment-modal-backdrop"
on:keyup={clickOnEnter}
on:click={handleBLur}
bind:this={backdrop}>
<div
class="modal payment-modal"
class:is-small={size === 'small'}
class:is-big={size === 'big'}
class:is-separate-header={headerDivider}>
<Form isModal {onSubmit}>
<header class="modal-header">
<div class="u-flex u-main-space-between u-cross-center u-gap-16">
<div class="u-flex u-cross-center u-gap-16">
{#if icon}
<div
class="avatar is-medium"
class:is-success={state === 'success'}
class:is-warning={state === 'warning'}
class:is-danger={state === 'error'}
class:is-info={state === 'info'}>
<span class={`icon-${icon}`} aria-hidden="true" />
</div>
{/if}
<h4 class="modal-title heading-level-5">
<slot name="title">
{title}
</slot>
</h4>
</div>
{#if closable}
<button
type="button"
class="button is-text is-only-icon"
style="--button-size:1.5rem;"
aria-label="Close Modal"
title="Close Modal"
on:click={() =>
trackEvent('click_close_modal', {
from: 'button'
})}
on:click={closeModal}>
<span class="icon-x" aria-hidden="true" />
</button>
{/if}
</div>
</header>
<div class="modal-content">
{#if error}
<Alert
dismissible
type="warning"
on:dismiss={() => {
error = null;
}}>
{error}
</Alert>
{/if}
<slot />
</div>
{#if $$slots.footer}
<div class="modal-footer">
<div class="u-flex u-main-end u-gap-16">
<slot name="footer" />
</div>
</div>
{/if}
</Form>
</div>
</div>
<style lang="scss">
.payment-modal-backdrop {
position: fixed;
top: 0;
left: 0;
z-index: 100000;
width: 100%;
height: 100%;
background-color: hsl(240 22% 10% / 0.3);
display: flex;
align-items: center;
justify-content: center;
:global() {
background-color: hsl(240 5% 8% / 0.6);
}
}
</style>
+1
View File
@@ -67,3 +67,4 @@ export { default as SvgIcon } from './svgIcon.svelte';
export { default as MigrationBox } from './migrationBox.svelte';
export { default as FloatingActionBar } from './floatingActionBar.svelte';
export { default as LoadingDots } from './loadingDots.svelte';
export { default as FakeModal } from './fakeModal.svelte';
@@ -1,23 +1,18 @@
<script lang="ts">
import { Alert } from '$lib/components';
import { FakeModal } from '$lib/components';
import { InputText, Button, FormList } from '$lib/elements/forms';
import { onMount } from 'svelte';
import { initializeStripe, submitStripeCard } from '$lib/stores/stripe';
import { invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
import { addNotification } from '$lib/stores/notifications';
import Form from '$lib/elements/forms/form.svelte';
import { trackEvent } from '$lib/actions/analytics';
import { clickOnEnter } from '$lib/helpers/a11y';
export let show = false;
let name: string;
let error: string;
let backdrop: HTMLDivElement;
onMount(async () => {
document.body.appendChild(backdrop);
await initializeStripe();
});
@@ -25,7 +20,7 @@
try {
await submitStripeCard(name);
invalidate(Dependencies.PAYMENT_METHODS);
closeModal();
show = false;
addNotification({
type: 'success',
message: 'A new payment method has been added to your account'
@@ -35,121 +30,25 @@
console.log(e.message);
}
}
function handleBLur(event: MouseEvent) {
if (event.target === backdrop) {
trackEvent('click_close_modal', {
from: 'backdrop'
});
closeModal();
}
}
function closeModal() {
if (show) {
show = false;
document.documentElement.classList.remove('u-overflow-hidden');
}
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') {
event.preventDefault();
trackEvent('click_close_modal', {
from: 'escape'
});
closeModal();
}
}
$: if (show) {
document.documentElement.classList.add('u-overflow-hidden');
} else {
closeModal();
error = null;
}
</script>
<svelte:window on:keydown={handleKeydown} />
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="payment-modal-backdrop"
on:keyup={clickOnEnter}
on:click={handleBLur}
bind:this={backdrop}>
<div class="modal is-big payment-modal">
<Form isModal onSubmit={handleSubmit}>
<header class="modal-header">
<div class="u-flex u-main-space-between u-cross-center u-gap-16">
<div class="u-flex u-cross-center u-gap-16">
<h4 class="modal-title heading-level-5">Add payment method</h4>
</div>
<button
type="button"
class="button is-text is-only-icon"
style="--button-size:1.5rem;"
aria-label="Close Modal"
title="Close Modal"
on:click={() =>
trackEvent('click_close_modal', {
from: 'button'
})}
on:click={closeModal}>
<span class="icon-x" aria-hidden="true" />
</button>
</div>
</header>
<div class="modal-content">
{#if error}
<Alert
dismissible
type="warning"
on:dismiss={() => {
error = null;
}}>
{error}
</Alert>
{/if}
<FormList gap={16}>
<InputText
id="name"
label="Cardholder name"
placeholder="Cardholder name"
bind:value={name}
required
autofocus={true}
hideRequired />
<FakeModal bind:show title="Add payment method" bind:error onSubmit={handleSubmit}>
<FormList gap={16}>
<InputText
id="name"
label="Cardholder name"
placeholder="Cardholder name"
bind:value={name}
required
autofocus={true}
hideRequired />
<div id="payment-element">
<!-- Elements will create form elements here -->
</div>
</FormList>
</div>
<div class="modal-footer">
<div class="u-flex u-main-end u-gap-16">
<Button secondary on:click={() => (show = false)}>Cancel</Button>
<Button submit disabled={!name}>Save</Button>
</div>
</div>
</Form>
</div>
</div>
<style lang="scss">
.payment-modal-backdrop {
position: fixed;
top: 0;
left: 0;
z-index: 100000;
width: 100%;
height: 100%;
background-color: hsl(240 22% 10% / 0.3);
display: flex;
align-items: center;
justify-content: center;
:global() {
background-color: hsl(240 5% 8% / 0.6);
}
}
</style>
<div id="payment-element">
<!-- Elements will create form elements here -->
</div>
</FormList>
<svelte:fragment slot="footer">
<Button secondary on:click={() => (show = false)}>Cancel</Button>
<Button submit disabled={!name}>Save</Button>
</svelte:fragment>
</FakeModal>
@@ -1,6 +1,6 @@
<script lang="ts">
import { invalidate } from '$app/navigation';
import { CreditCardBrandImage, Modal } from '$lib/components';
import { CreditCardBrandImage, FakeModal } from '$lib/components';
import { Button, FormList, InputRadio, InputText } from '$lib/elements/forms';
import { sdk } from '$lib/stores/sdk';
import { organization } from '$lib/stores/organization';
@@ -30,12 +30,10 @@
// TODO: fix new payment method replacement
async function handleSubmit() {
try {
console.log(selectedPaymentMethodId);
if (!selectedPaymentMethodId) {
const method = await submitStripeCard(name);
selectedPaymentMethodId = method.$id;
}
console.log(selectedPaymentMethodId);
isBackup
? await addBackupPaymentMethod(selectedPaymentMethodId)
: await addPaymentMethod(selectedPaymentMethodId);
@@ -95,7 +93,7 @@
}
</script>
<Modal
<FakeModal
bind:show
bind:error
onSubmit={handleSubmit}
@@ -103,61 +101,66 @@
headerDivider={false}
title="Replace payment method">
<p class="text">Replace the existing payment method for your organization.</p>
<div class:boxes-wrapper={methods?.total}>
{#if methods?.total}
{#each filteredMethods as method}
<div class="box">
<FormList>
<div class:boxes-wrapper={methods?.total}>
{#if methods?.total}
{#each filteredMethods as method}
<div class="box">
<InputRadio
id={`payment-method-${method.$id}`}
disabled={isBackup
? method.$id === $organization.paymentMethodId
: method.$id === $organization.backupPaymentMethodId}
value={method.$id}
name="payment"
bind:group={selectedPaymentMethodId}>
<span class="u-flex u-gap-16 u-main-space-between">
<span
class="u-flex u-cross-center u-gap-8"
style="padding-inline:0.25rem">
<span>
<span class="u-capitalize">{method.brand}</span> ending in {method.last4}</span>
<CreditCardBrandImage brand={method.brand} />
</span>
{#if method.$id === $organization.backupPaymentMethodId}
<Pill>Backup</Pill>
{:else if method.$id === $organization.paymentMethodId}
<Pill>Default</Pill>
{/if}
</span>
</InputRadio>
</div>
{/each}
{/if}
<div class="box">
{#if methods?.total}
<InputRadio
id={`payment-method-${method.$id}`}
disabled={isBackup
? method.$id === $organization.paymentMethodId
: method.$id === $organization.backupPaymentMethodId}
value={method.$id}
id="payment-method"
value={null}
name="payment"
bind:group={selectedPaymentMethodId}>
<span class="u-flex u-gap-16 u-main-space-between">
<span class="u-flex u-cross-center u-gap-8">
<span>
<span class="u-capitalize">{method.brand}</span> ending in {method.last4}</span>
<CreditCardBrandImage brand={method.brand} />
</span>
{#if method.$id === $organization.backupPaymentMethodId}
<Pill>Backup</Pill>
{:else if method.$id === $organization.paymentMethodId}
<Pill>Default</Pill>
{/if}
</span>
<span style="padding-inline:0.25rem">Add new payment method</span>
</InputRadio>
</div>
{/each}
{/if}
{/if}
{#if selectedPaymentMethodId === null}
<FormList>
<InputText
id="name"
label="Cardholder name"
placeholder="Cardholder name"
bind:value={name}
required
autofocus={true} />
<div class="box">
{#if methods?.total}
<InputRadio
id="payment-method"
label="Add new payment method"
value={null}
name="payment"
bind:group={selectedPaymentMethodId} />
{/if}
{#if selectedPaymentMethodId === null}
<FormList>
<InputText
id="name"
label="Cardholder name"
placeholder="Cardholder name"
bind:value={name}
required
autofocus={true} />
<div id="payment-element">
<!-- Elements will create form elements here -->
</div>
</FormList>
{/if}
<div id="payment-element">
<!-- Elements will create form elements here -->
</div>
</FormList>
{/if}
</div>
</div>
</div>
</FormList>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button
@@ -167,4 +170,4 @@
(isBackup ? $organization.backupPaymentMethodId : $organization.paymentMethodId)}
>Save</Button>
</svelte:fragment>
</Modal>
</FakeModal>
@@ -18,6 +18,7 @@
$: if ($changeOrganizationTier.billingPlan === 'tier-0' && $changeTierSteps) {
$changeTierSteps = updateStepStatus($changeTierSteps, 2, true);
$changeTierSteps = updateStepStatus($changeTierSteps, 3, true);
$changeTierSteps = updateStepStatus($changeTierSteps, 4, true);
}
$: if (
@@ -26,6 +27,7 @@
) {
$changeTierSteps = updateStepStatus($changeTierSteps, 2, false);
$changeTierSteps = updateStepStatus($changeTierSteps, 3, false);
$changeTierSteps = updateStepStatus($changeTierSteps, 4, false);
}
$: if ($changeOrganizationTier.billingPlan) {
@@ -73,10 +75,12 @@
members = await sdk.forConsole.teams.listMemberships($organization.$id);
//Select closest tier from starting one
if ($organization.billingPlan === 'tier-2') {
$changeOrganizationTier.billingPlan = 'tier-1';
} else if ($organization.billingPlan === 'tier-1') {
$changeOrganizationTier.billingPlan = 'tier-2';
// if ($organization.billingPlan === 'tier-2') {
// $changeOrganizationTier.billingPlan = 'tier-1';
// }
// else
if ($organization.billingPlan === 'tier-1') {
$changeOrganizationTier.billingPlan = 'tier-0';
} else if ($organization.billingPlan === 'tier-0') {
$changeOrganizationTier.billingPlan = 'tier-1';
}
@@ -1,7 +1,7 @@
<script lang="ts">
import { Box, CreditCardBrandImage } from '$lib/components';
import { Pill } from '$lib/elements';
import { InputTextarea } from '$lib/elements/forms';
import { FormList, InputTextarea } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { WizardStep } from '$lib/layout';
import { plansInfo } from '$lib/stores/billing';
@@ -56,11 +56,13 @@
know.
</svelte:fragment>
<!-- TODO: submit feedback -->
<InputTextarea
id="comment"
label="Your feedback here"
placeholder="This is my reason for downgrading..."
bind:value={comment} />
<FormList>
<InputTextarea
id="comment"
label="Your feedback here"
placeholder="This is my reason for downgrading..."
bind:value={comment} />
</FormList>
</WizardStep>
{:else}
<WizardStep>