Merge branch 'main' into feat-budget-nullable

This commit is contained in:
Damodar Lohani
2025-02-19 14:50:24 +05:45
committed by GitHub
12 changed files with 113 additions and 22 deletions
+2 -2
View File
@@ -95,7 +95,7 @@ importers:
version: 6.6.3
'@testing-library/svelte':
specifier: ^5.2.4
version: 5.2.4(svelte@4.2.19)(vite@5.4.11(@types/node@22.9.0)(sass@1.81.0))(vitest@1.6.1)
version: 5.2.4(svelte@4.2.19)(vite@5.4.11(@types/node@22.9.0)(sass@1.81.0))(vitest@1.6.1(@types/node@22.9.0)(@vitest/ui@1.6.0)(jsdom@22.1.0)(sass@1.81.0))
'@testing-library/user-event':
specifier: ^14.5.2
version: 14.5.2(@testing-library/dom@10.4.0)
@@ -5078,7 +5078,7 @@ snapshots:
lodash: 4.17.21
redent: 3.0.0
'@testing-library/svelte@5.2.4(svelte@4.2.19)(vite@5.4.11(@types/node@22.9.0)(sass@1.81.0))(vitest@1.6.1)':
'@testing-library/svelte@5.2.4(svelte@4.2.19)(vite@5.4.11(@types/node@22.9.0)(sass@1.81.0))(vitest@1.6.1(@types/node@22.9.0)(@vitest/ui@1.6.0)(jsdom@22.1.0)(sass@1.81.0))':
dependencies:
'@testing-library/dom': 10.4.0
svelte: 4.2.19
@@ -17,7 +17,7 @@
async function addCoupon() {
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = response;
dispatch('validation', couponData);
coupon = null;
@@ -18,7 +18,7 @@
async function addCoupon() {
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = response;
dispatch('validation', couponData);
coupon = null;
+10 -4
View File
@@ -1,9 +1,15 @@
<script>
export let hideSidebar = false;
</script>
<div class="wizard-secondary-content">
<div class="wizard-secondary-content-1">
<slot />
</div>
<div class="wizard-secondary-content-sep"></div>
<div class="wizard-secondary-content-2">
<slot name="aside" />
</div>
{#if !hideSidebar}
<div class="wizard-secondary-content-sep"></div>
<div class="wizard-secondary-content-2">
<slot name="aside" />
</div>
{/if}
</div>
+17 -1
View File
@@ -891,7 +891,7 @@ export class Billing {
}
}
async getCoupon(couponId: string): Promise<Coupon> {
async getCouponAccount(couponId: string): Promise<Coupon> {
const path = `/account/coupons/${couponId}`;
const params = {
couponId
@@ -907,6 +907,22 @@ export class Billing {
);
}
async getCoupon(couponId: string): Promise<Coupon> {
const path = `/console/coupons/${couponId}`;
const params = {
couponId
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'GET',
uri,
{
'content-type': 'application/json'
},
params
);
}
async setBillingAddress(
organizationId: string,
billingAddressId: string
+1 -1
View File
@@ -465,7 +465,7 @@ export async function checkForNewDevUpgradePro(org: Organization) {
if (isDismissed) return;
// check if coupon already applied
try {
await sdk.forConsole.billing.getCoupon(NEW_DEV_PRO_UPGRADE_COUPON);
await sdk.forConsole.billing.getCouponAccount(NEW_DEV_PRO_UPGRADE_COUPON);
} catch (e) {
return;
}
+63 -5
View File
@@ -13,7 +13,7 @@
import { app } from '$lib/stores/app';
import { addNotification } from '$lib/stores/notifications';
import { organizationList, type Organization } from '$lib/stores/organization';
import { ID } from '@appwrite.io/console';
import { BillingPlan, ID } from '@appwrite.io/console';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import { CreditsApplied } from '$lib/components/billing';
@@ -59,6 +59,10 @@
$: selectedAction = selectedOrgId === newOrgId ? 'create' : 'update';
onMount(async () => {
if (!$organizationList?.total && couponData?.code) {
goto(`${base}/create-organization?coupon=${couponData.code}&plan=${BillingPlan.Tier1}`);
}
if (!$organizationList?.total || campaign?.onlyNewOrgs) {
selectedOrgId = newOrgId;
}
@@ -134,7 +138,7 @@
<WizardSecondaryContainer href={previousPage} bind:showExitModal confirmExit>
<svelte:fragment slot="title">Apply credits</svelte:fragment>
<WizardSecondaryContent>
<WizardSecondaryContent hideSidebar={!$organizationList?.total}>
<Form bind:this={formComponent} onSubmit={handleSubmit} bind:isSubmitting>
<FormList gap={8}>
{#if $organizationList?.total && !campaign?.onlyNewOrgs && canSelectOrg}
@@ -147,6 +151,59 @@
id="organization" />
{/if}
<!-- TEMP FIX -->
{#if !$organizationList?.total}
{#if campaign?.template === 'card'}
<div
class="box card-container u-position-relative"
style:--box-border-radius="var(--border-radius-small)">
<div class="card-bg"></div>
<div
class="u-flex u-flex-vertical u-gap-24 u-cross-center u-position-relative">
<img
src={campaign?.image[$app.themeInUse]}
class="u-block u-image-object-fit-cover card-img"
alt="promo" />
<p class="text">
{#if couponData?.credits}
{campaign.title.replace(
'VALUE',
couponData.credits.toString()
)}
{:else}
{campaign.title}
{/if}
</p>
</div>
</div>
{/if}
<section
class="card u-margin-block-start-24"
style:--p-card-padding="1.5rem"
style:--p-card-border-radius="var(--border-radius-small)">
{#if couponData?.code && couponData?.status === 'active'}
{@const dateAvailable = selectedOrg?.billingNextInvoiceDate}
<CreditsApplied
bind:couponData
fixedCoupon={!!data?.couponData?.code} />
<p class="text u-margin-block-start-12">
{#if !dateAvailable}
Credits will automatically be applied to your next invoice.
{:else}
Credits will automatically be applied to your next invoice on <b
>{toLocaleDate(selectedOrg?.billingNextInvoiceDate)}</b
>.
{/if}
</p>
{:else}
<p class="text">
Add a coupon code to apply credits to your organization.
</p>
{/if}
</section>
{/if}
{#if campaign?.plan && selectedOrg && selectedOrg.billingPlan !== campaign?.plan}
<Helper type="neutral">
This coupon code is only valid when upgrading to Scale plan.
@@ -214,13 +271,14 @@
{#if $isSubmitting}
<span class="loader is-small is-transparent u-line-height-1-5" aria-hidden="true" />
{/if}
{#if selectedOrgId === newOrgId}
<!-- {#if selectedOrgId === newOrgId}
Create organization
{:else if campaign?.plan && selectedOrg && selectedOrg.billingPlan !== campaign?.plan}
Upgrade plan
{:else}
Apply credits
{/if}
Apply credits
{/if} -->
Apply credits
</Button>
</WizardSecondaryFooter>
<svelte:fragment slot="exit">
+1 -1
View File
@@ -12,7 +12,7 @@ export const load: PageLoad = async ({ url }) => {
let campaign: Campaign;
const code = url.searchParams.get('code');
try {
couponData = await sdk.forConsole.billing.getCoupon(code);
couponData = await sdk.forConsole.billing.getCouponAccount(code);
if (couponData.campaign) {
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
}
@@ -61,7 +61,7 @@
if ($page.url.searchParams.has('coupon')) {
const coupon = $page.url.searchParams.get('coupon');
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = response;
} catch (e) {
couponData = {
@@ -17,7 +17,7 @@
async function validateCoupon() {
if (couponData?.status === 'active') return;
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = response;
$addCreditWizardStore.coupon = coupon;
coupon = null;
@@ -83,7 +83,7 @@
if ($page.url.searchParams.has('code')) {
const coupon = $page.url.searchParams.get('code');
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = response;
} catch (e) {
couponData = {
+14 -3
View File
@@ -58,7 +58,18 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
}
};
function withParams(pathname: string, searchParams: URLSearchParams) {
if (searchParams.size > 0) return `${pathname}?${searchParams.toString()}`;
return pathname;
function withParams(pathname: string, searchParams: URLSearchParams): string {
const redirect = searchParams.get('redirect');
if (redirect) {
const extras = new URLSearchParams(searchParams);
extras.delete('redirect');
const extraQuery = extras.toString();
const finalRedirect = extraQuery
? `${redirect}${redirect.includes('?') ? '&' : '?'}${extraQuery}`
: redirect;
return `${pathname}?redirect=${encodeURIComponent(finalRedirect)}`;
}
const query = searchParams.toString();
return query ? `${pathname}?${query}` : pathname;
}