* feat: Add trial days to organization subscriptions and workspace warning - Add ORGANIZATION_TRIAL_DAYS environment variable for configurable trial periods - Implement trial days in Stripe checkout session (only when env var is set) - Add warning message to organization setup page about workspace structure - Add translation string for organization trial workspace warning - Add ORGANIZATION_TRIAL_DAYS to turbo.json env vars - Fix pre-existing linting warnings in CreateANewOrganizationForm.tsx - Add ESLint disable comments for turbo/no-undeclared-env-vars warnings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Rename variable * Add trial days to `purchaseTeamOrOrgSubscription` * fix: Move organization trial warning to spot 3 below form card - Add optional footer prop to WizardLayout component - Use footer prop in create-new-view.tsx to render warning at spot 3 - Remove warning from inside CreateANewOrganizationForm component - Warning now appears below the form card as requested Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: Add organization trial warning to all wizard steps - Add warning footer to step 2 (about-view.tsx) - Add warning footer to step 3 (add-teams-view.tsx) - Add warning footer to step 4 (onboard-members-view.tsx) - Add warning footer to step 5 (payment-status-view.tsx) - Add warning footer to resume-view.tsx (step 1 resume page) - Warning now appears on all steps of the organization creation wizard Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Correct environment variable name to STRIPE_ORG_TRIAL_DAYS - Changed ORGANIZATION_TRIAL_DAYS to STRIPE_ORG_TRIAL_DAYS in turbo.json - This matches the actual usage in OrganizationPaymentService.ts and payments.ts - Ensures the environment variable is properly recognized by the build system Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: Create shared OrganizationWizardLayout component - Create OrganizationWizardLayout component that wraps WizardLayout - Centralizes the trial warning footer logic in one place - Update all 6 wizard pages to use the shared component: - create-new-view.tsx - about-view.tsx - add-teams-view.tsx - onboard-members-view.tsx - payment-status-view.tsx - resume-view.tsx - Remove duplicate useLocale/Alert imports and footer props from pages - Simplifies maintenance by having warning logic in a single location Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix lint error * Add `ORG_TRIAL_DAYS` as constant * Add comment * Ensure no negative number is passed --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
|
|
import { usePathname } from "next/navigation";
|
|
import React, { useEffect, useState } from "react";
|
|
import { Toaster } from "sonner";
|
|
|
|
import { APP_NAME } from "@calcom/lib/constants";
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|
|
|
import { Button } from "../../components/button/Button";
|
|
import { StepCard } from "../../components/card/StepCard";
|
|
import { Steps } from "../../components/form/step/Steps";
|
|
import { SkeletonText } from "../../components/skeleton/Skeleton";
|
|
|
|
export function WizardLayout({
|
|
children,
|
|
maxSteps = 2,
|
|
currentStep = 0,
|
|
isOptionalCallback,
|
|
footer,
|
|
}: {
|
|
children: React.ReactNode;
|
|
} & { maxSteps?: number; currentStep?: number; isOptionalCallback?: () => void; footer?: React.ReactNode }) {
|
|
const { t, isLocaleReady } = useLocale();
|
|
const [meta, setMeta] = useState({ title: "", subtitle: " " });
|
|
const pathname = usePathname();
|
|
const { title, subtitle } = meta;
|
|
|
|
useEffect(() => {
|
|
setMeta({
|
|
title: window.document.title,
|
|
subtitle: window.document.querySelector('meta[name="description"]')?.getAttribute("content") || "",
|
|
});
|
|
}, [pathname]);
|
|
|
|
return (
|
|
<div className="bg-default text-emphasis min-h-screen" data-testid="onboarding">
|
|
<div>
|
|
<Toaster position="bottom-right" />
|
|
</div>
|
|
<div className="mx-auto px-4 py-24">
|
|
<div className="relative">
|
|
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
|
<div className="mx-auto sm:max-w-[520px]">
|
|
<header>
|
|
{isLocaleReady ? (
|
|
<>
|
|
<p className="font-cal mb-3 text-[28px] font-medium leading-7">
|
|
{title.replace(` | ${APP_NAME}`, "")}
|
|
</p>
|
|
<p className="text-subtle font-sans text-sm font-normal">{subtitle} </p>
|
|
</>
|
|
) : (
|
|
<>
|
|
<SkeletonText className="h-6 w-1/2" />
|
|
<SkeletonText className="mt-4 h-4 w-3/4" />
|
|
</>
|
|
)}
|
|
</header>
|
|
<Steps maxSteps={maxSteps} currentStep={currentStep} disableNavigation />
|
|
</div>
|
|
<StepCard>{children}</StepCard>
|
|
{footer && <div className="mt-4">{footer}</div>}
|
|
</div>
|
|
</div>
|
|
{isOptionalCallback && (
|
|
<div className="mt-4 flex justify-center">
|
|
<Button data-testid="handle-later-button" color="minimal" onClick={isOptionalCallback}>
|
|
{t("ill_do_this_later")}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export const getLayout = (page: React.ReactElement) => <WizardLayout>{page}</WizardLayout>;
|