mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-22 10:08:42 -06:00
feat: Rework the loading.tsx on PRODUCT pages (#2666)
Co-authored-by: Matti Nannt <mail@matthiasnannt.com>
This commit is contained in:
@@ -1,25 +1,34 @@
|
||||
const LoadingCard = ({ title, description }) => {
|
||||
"use client";
|
||||
|
||||
import { BrushIcon, KeyIcon, LanguagesIcon, ListChecksIcon, TagIcon, UsersIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
|
||||
import { PageHeader } from "@formbricks/ui/PageHeader";
|
||||
|
||||
const LoadingCard = () => {
|
||||
return (
|
||||
<div className="my-4 rounded-lg border border-slate-200">
|
||||
<div className="grid content-center rounded-lg bg-slate-100 px-6 py-5 text-left text-slate-900">
|
||||
<h3 className="text-lg font-medium leading-6">{title}</h3>
|
||||
<p className="mt-1 text-sm text-slate-500">{description}</p>
|
||||
<div className="w-full max-w-4xl rounded-xl border border-slate-200 bg-white py-4 shadow-sm">
|
||||
<div className="grid content-center border-b border-slate-200 px-4 pb-4 text-left text-slate-900">
|
||||
<h3 className="h-6 w-full max-w-56 animate-pulse rounded-lg bg-gray-100 text-lg font-medium leading-6"></h3>
|
||||
<p className="mt-3 h-4 w-full max-w-80 animate-pulse rounded-lg bg-gray-100 text-sm text-slate-500 "></p>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="rounded-lg px-6 py-5 hover:bg-slate-100">
|
||||
<div className="flex justify-end">
|
||||
<div className="mt-4 h-6 w-28 animate-pulse rounded-full bg-slate-200"></div>
|
||||
</div>
|
||||
<div className="mt-6 rounded-lg border border-slate-200">
|
||||
<div className="grid h-12 grid-cols-9 content-center rounded-t-lg bg-slate-100 px-6 text-left text-sm font-semibold text-slate-900">
|
||||
<div className="col-span-2">Label</div>
|
||||
<div className="col-span-2">API Key</div>
|
||||
<div className="col-span-2">Last used</div>
|
||||
<div className="col-span-2">Created at</div>
|
||||
<div className="rounded-lg px-4 pt-4 ">
|
||||
<div className="rounded-lg border border-slate-200">
|
||||
<div className="grid h-12 grid-cols-10 content-center rounded-t-lg bg-slate-100 px-6 text-left text-sm font-semibold text-slate-900">
|
||||
<div className="col-span-4 sm:col-span-2">Label</div>
|
||||
<div className="col-span-4 hidden sm:col-span-5 sm:block">API Key</div>
|
||||
<div className="col-span-4 sm:col-span-2">Created at</div>
|
||||
</div>
|
||||
<div className="px-6">
|
||||
<div className="my-4 h-6 w-full animate-pulse rounded-full bg-slate-200"></div>
|
||||
<div className="my-4 h-6 w-full animate-pulse rounded-full bg-slate-200"></div>
|
||||
<div className="my-4 h-5 w-full animate-pulse rounded-full bg-slate-200"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-start">
|
||||
<div className="mt-4 flex h-7 w-44 animate-pulse flex-col items-center justify-center rounded-md bg-black text-sm text-white">
|
||||
Loading
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,23 +38,76 @@ const LoadingCard = ({ title, description }) => {
|
||||
};
|
||||
|
||||
const Loading = () => {
|
||||
const cards = [
|
||||
const pathname = usePathname();
|
||||
|
||||
let navigation = [
|
||||
{
|
||||
title: "Development Env Keys",
|
||||
description: "Add and remove API keys for your Development environment.",
|
||||
id: "general",
|
||||
label: "General",
|
||||
icon: <UsersIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/general"),
|
||||
},
|
||||
{
|
||||
title: "Production Env Keys",
|
||||
description: "Add and remove API keys for your Production environment.",
|
||||
id: "look",
|
||||
label: "Look & Feel",
|
||||
icon: <BrushIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/look"),
|
||||
},
|
||||
{
|
||||
id: "languages",
|
||||
label: "Survey Languages",
|
||||
icon: <LanguagesIcon className="h-5 w-5" />,
|
||||
hidden: true,
|
||||
current: pathname?.includes("/languages"),
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
label: "Tags",
|
||||
icon: <TagIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/tags"),
|
||||
},
|
||||
{
|
||||
id: "api-keys",
|
||||
label: "API Keys",
|
||||
icon: <KeyIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/api-keys"),
|
||||
},
|
||||
{
|
||||
id: "setup",
|
||||
label: "Setup Guide",
|
||||
icon: <ListChecksIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/setup"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="my-4 text-2xl font-medium leading-6 text-slate-800">API Keys</h2>
|
||||
{cards.map((card, index) => (
|
||||
<LoadingCard key={index} {...card} />
|
||||
))}
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle="Configuration">
|
||||
<div className="grid h-10 w-full grid-cols-[auto,1fr] ">
|
||||
<nav className="flex h-full min-w-full items-center space-x-4" aria-label="Tabs">
|
||||
{navigation.map((navElem) => (
|
||||
<div
|
||||
key={navElem.id}
|
||||
className={cn(
|
||||
navElem.id === "api-keys"
|
||||
? "border-brand-dark border-b-2 font-semibold text-slate-900"
|
||||
: "border-transparent text-slate-500 transition-all duration-150 ease-in-out hover:border-slate-300 hover:text-slate-700",
|
||||
"flex h-full items-center border-b-2 px-3 text-sm font-medium",
|
||||
navElem.hidden && "hidden"
|
||||
)}
|
||||
aria-current={navElem.id === "api-keys" ? "page" : undefined}>
|
||||
{navElem.label}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
<div className="justify-self-end"></div>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div className="mt-4 flex max-w-4xl animate-pulse items-center space-y-4 rounded-lg border bg-blue-50 p-6 text-sm text-blue-900 shadow-sm md:space-y-0 md:text-base"></div>
|
||||
|
||||
<LoadingCard />
|
||||
</PageContentWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { BrushIcon, KeyIcon, LanguagesIcon, ListChecksIcon, TagIcon, UsersIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
|
||||
import { PageHeader } from "@formbricks/ui/PageHeader";
|
||||
|
||||
const LoadingCard = ({ title, description, skeletonLines }) => {
|
||||
return (
|
||||
<div className="my-4 rounded-lg border border-slate-200">
|
||||
<div className="grid content-center rounded-lg bg-slate-100 px-6 py-5 text-left text-slate-900">
|
||||
<div className="w-full max-w-4xl rounded-xl border border-slate-200 bg-white py-4 shadow-sm">
|
||||
<div className="grid content-center border-b border-slate-200 px-4 pb-4 text-left text-slate-900">
|
||||
<h3 className="text-lg font-medium leading-6">{title}</h3>
|
||||
<p className="mt-1 text-sm text-slate-500">{description}</p>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="rounded-lg px-6 py-5 hover:bg-slate-100">
|
||||
<div className="rounded-lg px-4 py-4 pb-0 pt-2 ">
|
||||
{skeletonLines.map((line, index) => (
|
||||
<div key={index} className="mt-4">
|
||||
<div className={`animate-pulse rounded-full bg-slate-200 ${line.classes}`}></div>
|
||||
@@ -19,6 +28,8 @@ const LoadingCard = ({ title, description, skeletonLines }) => {
|
||||
};
|
||||
|
||||
const Loading = () => {
|
||||
const pathname = usePathname();
|
||||
|
||||
const cards = [
|
||||
{
|
||||
title: "Product Name",
|
||||
@@ -38,12 +49,74 @@ const Loading = () => {
|
||||
},
|
||||
];
|
||||
|
||||
let navigation = [
|
||||
{
|
||||
id: "general",
|
||||
label: "General",
|
||||
icon: <UsersIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/general"),
|
||||
},
|
||||
{
|
||||
id: "look",
|
||||
label: "Look & Feel",
|
||||
icon: <BrushIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/look"),
|
||||
},
|
||||
{
|
||||
id: "languages",
|
||||
label: "Survey Languages",
|
||||
icon: <LanguagesIcon className="h-5 w-5" />,
|
||||
hidden: true,
|
||||
current: pathname?.includes("/languages"),
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
label: "Tags",
|
||||
icon: <TagIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/tags"),
|
||||
},
|
||||
{
|
||||
id: "api-keys",
|
||||
label: "API Keys",
|
||||
icon: <KeyIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/api-keys"),
|
||||
},
|
||||
{
|
||||
id: "setup",
|
||||
label: "Setup Guide",
|
||||
icon: <ListChecksIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/setup"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="my-4 text-2xl font-medium leading-6 text-slate-800">Product Settings</h2>
|
||||
{cards.map((card, index) => (
|
||||
<LoadingCard key={index} {...card} />
|
||||
))}
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle="Configuration">
|
||||
<div className="grid h-10 w-full grid-cols-[auto,1fr] ">
|
||||
<nav className="flex h-full min-w-full items-center space-x-4" aria-label="Tabs">
|
||||
{navigation.map((navElem) => (
|
||||
<div
|
||||
key={navElem.id}
|
||||
className={cn(
|
||||
navElem.id === "general"
|
||||
? "border-brand-dark border-b-2 font-semibold text-slate-900"
|
||||
: "border-transparent text-slate-500 transition-all duration-150 ease-in-out hover:border-slate-300 hover:text-slate-700",
|
||||
"flex h-full items-center border-b-2 px-3 text-sm font-medium",
|
||||
navElem.hidden && "hidden"
|
||||
)}
|
||||
aria-current={navElem.id === "general" ? "page" : undefined}>
|
||||
{navElem.label}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
<div className="justify-self-end"></div>
|
||||
</div>
|
||||
</PageHeader>
|
||||
{cards.map((card, index) => (
|
||||
<LoadingCard key={index} {...card} />
|
||||
))}
|
||||
</PageContentWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { SettingsCard } from "@/app/(app)/environments/[environmentId]/settings/components/SettingsCard";
|
||||
import { BrushIcon, KeyIcon, LanguagesIcon, ListChecksIcon, TagIcon, UsersIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { Badge } from "@formbricks/ui/Badge";
|
||||
import { Button } from "@formbricks/ui/Button";
|
||||
import { Label } from "@formbricks/ui/Label";
|
||||
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
|
||||
import { PageHeader } from "@formbricks/ui/PageHeader";
|
||||
import { RadioGroup, RadioGroupItem } from "@formbricks/ui/RadioGroup";
|
||||
import { Switch } from "@formbricks/ui/Switch";
|
||||
|
||||
@@ -16,130 +22,195 @@ const placements = [
|
||||
];
|
||||
|
||||
const Loading = () => {
|
||||
const pathname = usePathname();
|
||||
|
||||
let navigation = [
|
||||
{
|
||||
id: "general",
|
||||
label: "General",
|
||||
icon: <UsersIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/general"),
|
||||
},
|
||||
{
|
||||
id: "look",
|
||||
label: "Look & Feel",
|
||||
icon: <BrushIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/look"),
|
||||
},
|
||||
{
|
||||
id: "languages",
|
||||
label: "Survey Languages",
|
||||
icon: <LanguagesIcon className="h-5 w-5" />,
|
||||
hidden: true,
|
||||
current: pathname?.includes("/languages"),
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
label: "Tags",
|
||||
icon: <TagIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/tags"),
|
||||
},
|
||||
{
|
||||
id: "api-keys",
|
||||
label: "API Keys",
|
||||
icon: <KeyIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/api-keys"),
|
||||
},
|
||||
{
|
||||
id: "setup",
|
||||
label: "Setup Guide",
|
||||
icon: <ListChecksIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/setup"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SettingsCard
|
||||
title="Theme"
|
||||
className="max-w-7xl"
|
||||
description="Create a style theme for all surveys. You can enable custom styling for each survey.">
|
||||
<div className="flex animate-pulse">
|
||||
<div className="w-1/2">
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-4 rounded-lg bg-slate-50 p-4">
|
||||
<div className="flex items-center gap-6">
|
||||
<Switch />
|
||||
<div className="flex flex-col">
|
||||
<h3 className="text-sm font-semibold text-slate-700">Enable custom styling</h3>
|
||||
<p className="text-xs text-slate-500">
|
||||
Allow users to override this theme in the editor.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4 bg-slate-50 p-4">
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<h2 className="text-base font-semibold text-slate-700">Form Styling</h2>
|
||||
<p className="mt-1 text-sm text-slate-500">
|
||||
Style the question texts, descriptions and input fields.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<h2 className="text-base font-semibold text-slate-700">Card Styling</h2>
|
||||
<p className="mt-1 text-sm text-slate-500">Style the survey card.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<h2 className="text-base font-semibold text-slate-700">Background Styling</h2>
|
||||
<Badge text="Link Surveys" type="gray" size="normal" />
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-slate-500">
|
||||
Change the background to a color, image or animation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-1/2 bg-slate-100 px-6 pt-4">
|
||||
<div className="relative flex h-[95] max-h-[95%] w-full items-center justify-center rounded-lg border border-slate-300 bg-slate-200">
|
||||
<div className="flex h-full w-5/6 flex-1 flex-col">
|
||||
<div className="flex h-8 w-full items-center rounded-t-lg bg-slate-100">
|
||||
<div className="ml-6 flex space-x-2">
|
||||
<div className="h-3 w-3 rounded-full bg-red-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-amber-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-emerald-500"></div>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full justify-between font-mono text-sm text-slate-400">
|
||||
<p>Preview</p>
|
||||
|
||||
<div className="flex items-center pr-6">Restart</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid h-[500px] place-items-center bg-white">
|
||||
<h1 className="text-xl font-semibold text-slate-700">Loading preview...</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard
|
||||
title="In-app Survey Placement"
|
||||
description="Change where surveys will be shown in your web app.">
|
||||
<div className="w-full items-center">
|
||||
<div className="flex cursor-not-allowed select-none">
|
||||
<RadioGroup>
|
||||
{placements.map((placement) => (
|
||||
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap ">
|
||||
<RadioGroupItem
|
||||
className="cursor-not-allowed select-none"
|
||||
id={placement.value}
|
||||
value={placement.value}
|
||||
disabled={placement.disabled}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={placement.value}
|
||||
className={cn(
|
||||
placement.disabled ? "cursor-not-allowed text-slate-500" : "text-slate-900"
|
||||
)}>
|
||||
{placement.name}
|
||||
</Label>
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle="Configuration">
|
||||
<div className="grid h-10 w-full grid-cols-[auto,1fr] ">
|
||||
<nav className="flex h-full min-w-full items-center space-x-4" aria-label="Tabs">
|
||||
{navigation.map((navElem) => (
|
||||
<div
|
||||
key={navElem.id}
|
||||
className={cn(
|
||||
navElem.id === "look"
|
||||
? "border-brand-dark border-b-2 font-semibold text-slate-900"
|
||||
: "border-transparent text-slate-500 transition-all duration-150 ease-in-out hover:border-slate-300 hover:text-slate-700",
|
||||
"flex h-full items-center border-b-2 px-3 text-sm font-medium",
|
||||
navElem.hidden && "hidden"
|
||||
)}
|
||||
aria-current={navElem.id === "look" ? "page" : undefined}>
|
||||
{navElem.label}
|
||||
</div>
|
||||
))}
|
||||
</RadioGroup>
|
||||
<div className="relative ml-8 h-40 w-full rounded bg-slate-200">
|
||||
<div className={cn("absolute bottom-3 h-16 w-16 rounded bg-slate-700 sm:right-3")}></div>
|
||||
</nav>
|
||||
<div className="justify-self-end"></div>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<SettingsCard
|
||||
title="Theme"
|
||||
className="max-w-7xl"
|
||||
description="Create a style theme for all surveys. You can enable custom styling for each survey.">
|
||||
<div className="flex animate-pulse">
|
||||
<div className="w-1/2">
|
||||
<div className="flex flex-col gap-4 pr-6">
|
||||
<div className="flex flex-col gap-4 rounded-lg bg-slate-50 p-4">
|
||||
<div className="flex items-center gap-6">
|
||||
<Switch />
|
||||
<div className="flex flex-col">
|
||||
<h3 className="text-sm font-semibold text-slate-700">Enable custom styling</h3>
|
||||
<p className="text-xs text-slate-500">
|
||||
Allow users to override this theme in the editor.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 bg-slate-50 p-4">
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<h2 className="text-sm font-semibold text-slate-700">Form Styling</h2>
|
||||
<p className="mt-1 text-xs text-slate-500">
|
||||
Style the question texts, descriptions and input fields.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<h2 className="text-sm font-semibold text-slate-700">Card Styling</h2>
|
||||
<p className="mt-1 text-xs text-slate-500">Style the survey card.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full rounded-lg border border-slate-300 bg-white">
|
||||
<div className="flex flex-col p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<h2 className="text-sm font-semibold text-slate-700">Background Styling</h2>
|
||||
<Badge text="Link Surveys" type="gray" size="normal" />
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-slate-500">
|
||||
Change the background to a color, image or animation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative flex w-1/2 flex-row items-center justify-center rounded-lg bg-slate-100 pt-4">
|
||||
<div className="relative mb-3 flex h-fit w-5/6 items-center justify-center rounded-lg border border-slate-300 bg-slate-200">
|
||||
<div className="flex h-[95] max-h-[90%] w-4/6 flex-1 flex-col">
|
||||
<div className="flex h-8 w-full items-center rounded-t-lg bg-slate-100">
|
||||
<div className="ml-6 flex space-x-2">
|
||||
<div className="h-3 w-3 rounded-full bg-red-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-amber-500"></div>
|
||||
<div className="h-3 w-3 rounded-full bg-emerald-500"></div>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full justify-between font-mono text-sm text-slate-400">
|
||||
<p>Preview</p>
|
||||
|
||||
<div className="flex items-center pr-6">Restart</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid h-[500px] place-items-center bg-white">
|
||||
<h1 className="text-xl font-semibold text-slate-700">Loading preview...</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="darkCTA"
|
||||
className="pointer-events-none mt-4 animate-pulse cursor-not-allowed select-none bg-slate-200">
|
||||
Loading
|
||||
</Button>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard
|
||||
title="Formbricks Signature"
|
||||
description="We love your support but understand if you toggle it off.">
|
||||
<div className="w-full items-center">
|
||||
<div className="pointer-events-none flex cursor-not-allowed select-none items-center space-x-2">
|
||||
<Switch id="signature" checked={false} />
|
||||
<Label htmlFor="signature">Show 'Powered by Formbricks' Signature</Label>
|
||||
<SettingsCard
|
||||
title="In-app Survey Placement"
|
||||
description="Change where surveys will be shown in your web app.">
|
||||
<div className="w-full items-center">
|
||||
<div className="flex cursor-not-allowed select-none">
|
||||
<RadioGroup>
|
||||
{placements.map((placement) => (
|
||||
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap ">
|
||||
<RadioGroupItem
|
||||
className="cursor-not-allowed select-none"
|
||||
id={placement.value}
|
||||
value={placement.value}
|
||||
disabled={placement.disabled}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={placement.value}
|
||||
className={cn(
|
||||
placement.disabled ? "cursor-not-allowed text-slate-500" : "text-slate-900"
|
||||
)}>
|
||||
{placement.name}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</RadioGroup>
|
||||
<div className="relative ml-8 h-40 w-full rounded bg-slate-200">
|
||||
<div className={cn("absolute bottom-3 h-16 w-16 rounded bg-slate-700 sm:right-3")}></div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="darkCTA"
|
||||
className="pointer-events-none mt-4 animate-pulse cursor-not-allowed select-none bg-slate-200">
|
||||
Loading
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard
|
||||
title="Formbricks Signature"
|
||||
description="We love your support but understand if you toggle it off.">
|
||||
<div className="w-full items-center">
|
||||
<div className="pointer-events-none flex cursor-not-allowed select-none items-center space-x-2">
|
||||
<Switch id="signature" checked={false} />
|
||||
<Label htmlFor="signature">Show 'Powered by Formbricks' Signature</Label>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
</PageContentWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { BrushIcon, KeyIcon, LanguagesIcon, ListChecksIcon, TagIcon, UsersIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { PageContentWrapper } from "@formbricks/ui/PageContentWrapper";
|
||||
import { PageHeader } from "@formbricks/ui/PageHeader";
|
||||
|
||||
const LoadingCard = ({ title, description, skeletonLines }) => {
|
||||
return (
|
||||
<div className="my-4 rounded-lg border border-slate-200">
|
||||
<div className="grid content-center rounded-lg bg-slate-100 px-6 py-5 text-left text-slate-900">
|
||||
<div className="w-full max-w-4xl rounded-xl border border-slate-200 bg-white py-4 text-left shadow-sm">
|
||||
<div className="grid content-center border-b border-slate-200 px-4 pb-4 text-left text-slate-900">
|
||||
<h3 className="text-lg font-medium leading-6">{title}</h3>
|
||||
<p className="mt-1 text-sm text-slate-500">{description}</p>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="rounded-lg px-6 py-5 hover:bg-slate-100">
|
||||
<div className="rounded-lg px-4 ">
|
||||
{skeletonLines.map((line, index) => (
|
||||
<div key={index} className="mt-4">
|
||||
<div className={`animate-pulse bg-slate-200 ${line.classes}`}></div>
|
||||
<div
|
||||
className={`flex animate-pulse flex-col items-center justify-center space-y-2 rounded-lg bg-slate-200 py-6 text-center ${line.classes}`}></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -19,11 +29,18 @@ const LoadingCard = ({ title, description, skeletonLines }) => {
|
||||
};
|
||||
|
||||
const Loading = () => {
|
||||
const pathname = usePathname();
|
||||
|
||||
const cards = [
|
||||
{
|
||||
title: "Widget Status",
|
||||
description: "Check if the Formbricks widget is alive and kicking.",
|
||||
skeletonLines: [{ classes: "h-32 max-w-full rounded-md" }],
|
||||
skeletonLines: [{ classes: " h-44 max-w-full rounded-md" }],
|
||||
},
|
||||
{
|
||||
title: "Your EnvironmentId",
|
||||
description: "This Id uniquely identifies this Formbricks environment.",
|
||||
skeletonLines: [{ classes: "h-6 w-4/6 rounded-full" }],
|
||||
},
|
||||
{
|
||||
title: "How to setup",
|
||||
@@ -39,12 +56,75 @@ const Loading = () => {
|
||||
},
|
||||
];
|
||||
|
||||
let navigation = [
|
||||
{
|
||||
id: "general",
|
||||
label: "General",
|
||||
icon: <UsersIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/general"),
|
||||
},
|
||||
{
|
||||
id: "look",
|
||||
label: "Look & Feel",
|
||||
icon: <BrushIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/look"),
|
||||
},
|
||||
{
|
||||
id: "languages",
|
||||
label: "Survey Languages",
|
||||
icon: <LanguagesIcon className="h-5 w-5" />,
|
||||
hidden: true,
|
||||
current: pathname?.includes("/languages"),
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
label: "Tags",
|
||||
icon: <TagIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/tags"),
|
||||
},
|
||||
{
|
||||
id: "api-keys",
|
||||
label: "API Keys",
|
||||
icon: <KeyIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/api-keys"),
|
||||
},
|
||||
{
|
||||
id: "setup",
|
||||
label: "Setup Guide",
|
||||
icon: <ListChecksIcon className="h-5 w-5" />,
|
||||
current: pathname?.includes("/setup"),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="my-4 text-2xl font-medium leading-6 text-slate-800">Setup Checklist</h2>
|
||||
{cards.map((card, index) => (
|
||||
<LoadingCard key={index} {...card} />
|
||||
))}
|
||||
<PageContentWrapper>
|
||||
<PageHeader pageTitle="Configuration">
|
||||
<div className="grid h-10 w-full grid-cols-[auto,1fr] ">
|
||||
<nav className="flex h-full min-w-full items-center space-x-4" aria-label="Tabs">
|
||||
{navigation.map((navElem) => (
|
||||
<div
|
||||
key={navElem.id}
|
||||
className={cn(
|
||||
navElem.id === "setup"
|
||||
? "border-brand-dark border-b-2 font-semibold text-slate-900"
|
||||
: "border-transparent text-slate-500 transition-all duration-150 ease-in-out hover:border-slate-300 hover:text-slate-700",
|
||||
"flex h-full items-center border-b-2 px-3 text-sm font-medium",
|
||||
navElem.hidden && "hidden"
|
||||
)}
|
||||
aria-current={navElem.id === "setup" ? "page" : undefined}>
|
||||
{navElem.label}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
<div className="justify-self-end"></div>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div className="mt-4 flex max-w-4xl animate-pulse items-center space-y-4 rounded-lg border bg-blue-50 p-6 text-sm text-blue-900 shadow-sm md:space-y-0 md:text-base"></div>
|
||||
{cards.map((card, index) => (
|
||||
<LoadingCard key={index} {...card} />
|
||||
))}
|
||||
</PageContentWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user