Skip to content

Commit

Permalink
Merge branch '1229-feature-request-send-mail-when-team-trial-webhook-…
Browse files Browse the repository at this point in the history
…updates' into dev
  • Loading branch information
DonKoko committed Aug 14, 2024
2 parents e705353 + 76e2a2f commit 720af4c
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 69 deletions.
190 changes: 134 additions & 56 deletions app/components/subscription/successful-subscription-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,145 @@
import { useCallback } from "react";
import { useLoaderData } from "@remix-run/react";
import { BellIcon } from "@radix-ui/react-icons";
import { useBlocker } from "@remix-run/react";
import { AnimatePresence } from "framer-motion";
import { useSearchParams } from "~/hooks/search-params";

import type { loader } from "~/routes/_layout+/account-details.subscription";
import { Button } from "../shared/button";
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "../shared/modal";
import { WarningBox } from "../shared/warning-box";

export default function SuccessfulSubscriptionModal() {
const [params, setParams] = useSearchParams();
const success = params.get("success") || false;
const isTeam = params.get("team") || false;
const handleBackdropClose = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (e.target !== e.currentTarget) return;
params.delete("success");
setParams(params);
},
[params, setParams]
);

const { activeProduct } = useLoaderData<typeof loader>();
const [searchParams, setSearchParams] = useSearchParams();
const success = searchParams.get("success") || false;
const isTeam = searchParams.get("team") === "true";
const hasExistingWorkspace =
searchParams.get("hasExistingWorkspace") === "true";

return (
<AnimatePresence>
{success ? (
<div
className="dialog-backdrop !bg-[#364054]/70"
onClick={handleBackdropClose}
>
<dialog
className="dialog m-auto h-auto w-[90%] sm:w-[400px]"
open={true}
>
<div className="relative z-10 rounded bg-white p-6 shadow-lg">
<video height="200" autoPlay loop muted className="mb-6 rounded">
<source src="/static/videos/celebration.mp4" type="video/mp4" />
</video>
<div className="mb-8 text-center">
<h4 className="mb-1 text-[18px] font-semibold">
You are all set!
</h4>
<p className="text-gray-600">
{activeProduct?.name} features unlocked.{" "}
{isTeam && "Now, create a team workspace."}
</p>
</div>
{isTeam ? (
<Button
width="full"
to="/account-details/workspace/new"
variant="primary"
<>
<AnimatePresence>
{success ? (
<div className="dialog-backdrop !bg-[#364054]/70">
<dialog
className="dialog m-auto h-auto w-[90%] sm:w-[400px]"
open={true}
>
<div className="relative z-10 rounded bg-white p-6 shadow-lg">
<video
height="200"
autoPlay
loop
muted
className="mb-6 rounded"
>
Create your Team workspace
</Button>
) : (
<Button width="full" to="/assets" variant="primary">
Get started
</Button>
)}
</div>
</dialog>
</div>
) : null}
</AnimatePresence>
<source
src="/static/videos/celebration.mp4"
type="video/mp4"
/>
</video>
<div className="mb-8 text-center">
<h4 className="mb-1 text-[18px] font-semibold">
You are all set!
</h4>
<p className="text-gray-600">
{isTeam ? "Team" : "Plus"} features unlocked.{" "}
{isTeam && !hasExistingWorkspace
? "Now, it is time to create your team workspace and start adding assets."
: "Now, it is time to start adding assets. Make sure you are in the right workspace."}
</p>
</div>
{isTeam && !hasExistingWorkspace ? (
<>
<div className="my-4 text-gray-700">
<strong>IMPORTANT</strong>: To use the Team features you
need to use your Team workspace. Make sure to create it
before you continue.
</div>
<Button
width="full"
onClick={() => {
setSearchParams((prev) => {
/** We remove the success param as that controls this modal being visible */
prev.delete("success");
return prev;
});
}}
variant="primary"
>
Create Team workspace
</Button>
</>
) : (
<Button width="full" to="/assets" variant="primary">
Get started
</Button>
)}
</div>
</dialog>
</div>
) : null}
</AnimatePresence>
<AreYouSureModal shouldBlock={isTeam && !hasExistingWorkspace} />
</>
);
}

function AreYouSureModal({ shouldBlock }: { shouldBlock: boolean }) {
// Block navigating elsewhere when data has been entered into the input
const blocker = useBlocker(
({ currentLocation, nextLocation }) =>
shouldBlock && currentLocation.pathname !== nextLocation.pathname
);
return blocker && blocker.state === "blocked" ? (
<AlertDialog open={blocker.state === "blocked"}>
<AlertDialogContent>
<AlertDialogHeader>
<div className="mx-auto md:m-0">
<span className="flex size-12 items-center justify-center rounded-full bg-error-50 p-2 text-error-600">
<BellIcon />
</span>
</div>
<AlertDialogTitle>
Are you sure you want to leave the page?
</AlertDialogTitle>
<AlertDialogDescription>
You just got your team subscription. Do you want to leave without
creating a Team workspace?
</AlertDialogDescription>
<WarningBox className="my-4 ">
<>
{" "}
<strong>IMPORTANT</strong>: To use the Team features you need to
use your Team workspace. Make sure to create it before you
continue.
</>
</WarningBox>
</AlertDialogHeader>
<AlertDialogFooter>
<div className="flex w-full flex-col justify-center gap-2">
<Button
variant="secondary"
width="full"
onClick={() => blocker.reset()}
>
No, I want to stay.
</Button>

<Button
className="border-error-600 bg-error-600 hover:border-error-800 hover:bg-error-800"
onClick={() => blocker.proceed()}
>
Yes, I don't want a Team workspace
</Button>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
) : null;
}
23 changes: 22 additions & 1 deletion app/components/workspace/form.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useEffect, useRef } from "react";
import type { Organization, Currency } from "@prisma/client";
import { useLoaderData, useNavigation } from "@remix-run/react";
import { useAtom, useAtomValue } from "jotai";
import { useZorm } from "react-zorm";
import { z } from "zod";
import { updateDynamicTitleAtom } from "~/atoms/dynamic-title-atom";
import { fileErrorAtom, validateFileAtom } from "~/atoms/file";
import { useSearchParams } from "~/hooks/search-params";
import type { loader } from "~/routes/_layout+/account-details.workspace.new";
import { isFormProcessing } from "~/utils/form";
import { zodFieldIsRequired } from "~/utils/zod";
Expand Down Expand Up @@ -38,12 +40,21 @@ interface Props {

export const WorkspaceForm = ({ name, currency, children }: Props) => {
const { curriences } = useLoaderData<typeof loader>();
const [searchParams] = useSearchParams();
const navigation = useNavigation();
const zo = useZorm("NewQuestionWizardScreen", NewWorkspaceFormSchema);
const disabled = isFormProcessing(navigation.state);
const fileError = useAtomValue(fileErrorAtom);
const [, validateFile] = useAtom(validateFileAtom);
const [, updateTitle] = useAtom(updateDynamicTitleAtom);
const nameFieldRef = useRef<HTMLInputElement>(null);

useEffect(() => {
const team = searchParams.get("team");
if (!team && nameFieldRef.current) {
nameFieldRef.current.focus();
}
}, [searchParams]);

return (
<Card className="w-full md:w-min">
Expand All @@ -55,6 +66,9 @@ export const WorkspaceForm = ({ name, currency, children }: Props) => {
>
<FormRow
rowLabel={"Name"}
subHeading={
"Choose a name that represents your Organization. Make it easily recognizable for your team members."
}
className="border-b-0 pb-[10px] pt-0"
required={zodFieldIsRequired(NewWorkspaceFormSchema.shape.name)}
>
Expand All @@ -70,10 +84,17 @@ export const WorkspaceForm = ({ name, currency, children }: Props) => {
defaultValue={name || undefined}
placeholder=""
required={zodFieldIsRequired(NewWorkspaceFormSchema.shape.name)}
ref={nameFieldRef}
/>
</FormRow>

<FormRow rowLabel={"Main image"} className="border-b-0">
<FormRow
rowLabel={"Main image"}
className="border-b-0"
subHeading={
"Used to place your organization's logo or symbol. For best results, use a square image."
}
>
<div>
<p className="hidden lg:block">
Accepts PNG, JPG or JPEG (max.4 MB)
Expand Down
Loading

0 comments on commit 720af4c

Please sign in to comment.