mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 02:10:12 -06:00
UI: Responsiveness of Settings Menu
UI: Responsive of Settings Menu
This commit is contained in:
@@ -237,8 +237,7 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
|
||||
<div className="flex space-x-4 py-2">
|
||||
<Link
|
||||
href={`/environments/${environmentId}/surveys/`}
|
||||
className=" flex items-center justify-center rounded-md bg-gradient-to-b text-white transition-all ease-in-out hover:scale-105">
|
||||
{/* <PlusIcon className="h-6 w-6" /> */}
|
||||
className="flex items-center justify-center rounded-md bg-gradient-to-b text-white transition-all ease-in-out hover:scale-105">
|
||||
<Image src={FaveIcon} width={30} height={30} alt="faveicon" />
|
||||
</Link>
|
||||
|
||||
@@ -253,7 +252,7 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
|
||||
item.current
|
||||
? "bg-slate-100 text-slate-900"
|
||||
: "text-slate-900 hover:bg-slate-50 hover:text-slate-900",
|
||||
"hidden items-center rounded-md px-2 py-1 text-sm font-medium sm:inline-flex"
|
||||
"hidden items-center rounded-md px-2 py-1 text-sm font-medium lg:inline-flex"
|
||||
)}
|
||||
aria-current={item.current ? "page" : undefined}>
|
||||
<IconComponent className="mr-3 h-5 w-5" />
|
||||
@@ -263,7 +262,8 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center sm:hidden">
|
||||
{/* Mobile Menu */}
|
||||
<div className="flex items-center lg:hidden">
|
||||
<Popover open={mobileNavMenuOpen} onOpenChange={setMobileNavMenuOpen}>
|
||||
<PopoverTrigger onClick={() => setMobileNavMenuOpen(!mobileNavMenuOpen)}>
|
||||
<span>
|
||||
@@ -290,7 +290,8 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
<div className="hidden sm:ml-6 sm:flex sm:items-center">
|
||||
{/* User Dropdown */}
|
||||
<div className="hidden lg:ml-6 lg:flex lg:items-center">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<div className="flex cursor-pointer flex-row items-center space-x-5">
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function SettingsCard({
|
||||
}) {
|
||||
return (
|
||||
<div className="my-4 w-full bg-white shadow sm:rounded-lg">
|
||||
<div className="rounded-t-lg border-b border-slate-200 bg-slate-100 px-6 py-5">
|
||||
<div className="border-b border-slate-200 bg-slate-100 px-6 py-5">
|
||||
<div className="flex">
|
||||
<h3 className="text-lg font-medium leading-6 text-slate-900">{title}</h3>
|
||||
<div className="ml-2">
|
||||
|
||||
@@ -4,6 +4,8 @@ import { useProduct } from "@/lib/products/products";
|
||||
import { useTeam } from "@/lib/teams/teams";
|
||||
import { truncate } from "@/lib/utils";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui";
|
||||
import { ChevronDownIcon } from "@heroicons/react/20/solid";
|
||||
import {
|
||||
AdjustmentsVerticalIcon,
|
||||
BellAlertIcon,
|
||||
@@ -11,22 +13,24 @@ import {
|
||||
CreditCardIcon,
|
||||
DocumentCheckIcon,
|
||||
DocumentMagnifyingGlassIcon,
|
||||
HashtagIcon,
|
||||
KeyIcon,
|
||||
LinkIcon,
|
||||
PaintBrushIcon,
|
||||
HashtagIcon,
|
||||
UserCircleIcon,
|
||||
UsersIcon,
|
||||
} from "@heroicons/react/24/solid";
|
||||
import clsx from "clsx";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
export default function SettingsNavbar({ environmentId }: { environmentId: string }) {
|
||||
const pathname = usePathname();
|
||||
const { team } = useTeam(environmentId);
|
||||
const { product } = useProduct(environmentId);
|
||||
const [mobileNavMenuOpen, setMobileNavMenuOpen] = useState(false);
|
||||
|
||||
interface NavigationLink {
|
||||
name: string;
|
||||
href: string;
|
||||
@@ -41,7 +45,6 @@ export default function SettingsNavbar({ environmentId }: { environmentId: strin
|
||||
links: NavigationLink[];
|
||||
}
|
||||
|
||||
// Then, specify the type of the navigation array
|
||||
const navigation: NavigationSection[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -181,42 +184,96 @@ export default function SettingsNavbar({ environmentId }: { environmentId: strin
|
||||
if (!navigation) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed h-full bg-white py-2 pl-4 pr-10">
|
||||
<nav className="flex-1 space-y-1 bg-white px-2">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-6 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
className={clsx(
|
||||
link.current ? "bg-slate-100 text-slate-900" : "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
<>
|
||||
<div className="fixed hidden h-full bg-white py-2 pl-4 pr-10 md:block ">
|
||||
<nav className="flex-1 space-y-1 bg-white px-2">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-6 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
className={clsx(
|
||||
link.current ? "bg-slate-100 text-slate-900" : "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<div className="fixed z-10 flex h-14 w-full items-center justify-between border-b border-slate-200 bg-white px-4 sm:px-6 md:hidden">
|
||||
<Popover open={mobileNavMenuOpen} onOpenChange={setMobileNavMenuOpen}>
|
||||
<PopoverTrigger onClick={() => setMobileNavMenuOpen(!mobileNavMenuOpen)}>
|
||||
<span className="flex items-center">
|
||||
<span className="mr-1">Settings</span>
|
||||
<ChevronDownIcon className="h-5 w-5 text-slate-500" aria-hidden="true" />
|
||||
</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="shadow">
|
||||
<div className="flex flex-col">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-3 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
onClick={() => setMobileNavMenuOpen(false)}
|
||||
className={clsx(
|
||||
link.current
|
||||
? "bg-slate-100 text-slate-900"
|
||||
: "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,10 +60,10 @@ export default function EditAPIKeys({
|
||||
</div>
|
||||
<div className="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="col-span-4 sm:col-span-2">Label</div>
|
||||
<div className="col-span-4 hidden sm:col-span-2 sm:block">API Key</div>
|
||||
<div className="col-span-4 hidden sm:col-span-2 sm:block">Last used</div>
|
||||
<div className="col-span-4 sm:col-span-2">Created at</div>
|
||||
<div className=""></div>
|
||||
</div>
|
||||
<div className="grid-cols-9">
|
||||
@@ -77,12 +77,14 @@ export default function EditAPIKeys({
|
||||
<div
|
||||
className="grid h-12 w-full grid-cols-9 content-center rounded-lg px-6 text-left text-sm text-slate-900"
|
||||
key={apiKey.hashedKey}>
|
||||
<div className="col-span-2 font-semibold">{apiKey.label}</div>
|
||||
<div className="col-span-2">{apiKey.apiKey || <span className="italic">secret</span>}</div>
|
||||
<div className="col-span-2">
|
||||
<div className="col-span-4 font-semibold sm:col-span-2">{apiKey.label}</div>
|
||||
<div className="col-span-4 hidden sm:col-span-2 sm:block">
|
||||
{apiKey.apiKey || <span className="italic">secret</span>}
|
||||
</div>
|
||||
<div className="col-span-4 hidden sm:col-span-2 sm:block">
|
||||
{apiKey.lastUsedAt && timeSince(apiKey.lastUsedAt.toString())}
|
||||
</div>
|
||||
<div className="col-span-2">{timeSince(apiKey.createdAt.toString())}</div>
|
||||
<div className="col-span-4 sm:col-span-2">{timeSince(apiKey.createdAt.toString())}</div>
|
||||
<div className="col-span-1 text-center">
|
||||
<button onClick={(e) => handleOpenDeleteKeyModal(e, apiKey)}>
|
||||
<TrashIcon className="h-5 w-5 text-slate-700 hover:text-slate-500" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import SettingsNavbar from "./SettingsNavbar";
|
||||
import { Metadata } from "next";
|
||||
import SettingsNavbar from "./SettingsNavbar";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Settings",
|
||||
@@ -8,10 +8,10 @@ export const metadata: Metadata = {
|
||||
export default function SettingsLayout({ children, params }) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex">
|
||||
<div className="sm:flex">
|
||||
<SettingsNavbar environmentId={params.environmentId} />
|
||||
<div className="ml-64 w-full">
|
||||
<div className="max-w-4xl p-6">
|
||||
<div className="w-full md:ml-64">
|
||||
<div className="max-w-4xl px-6 pb-6 pt-14 md:pt-6">
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { DEFAULT_BRAND_COLOR } from "@formbricks/lib/constants";
|
||||
import { TProduct, TProductUpdateInput } from "@formbricks/types/v1/product";
|
||||
import { Button, ColorPicker, Label, Switch } from "@formbricks/ui";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { DEFAULT_BRAND_COLOR } from "@formbricks/lib/constants";
|
||||
import { TProduct, TProductUpdateInput } from "@formbricks/types/v1/product";
|
||||
import { updateProductAction } from "./actions";
|
||||
|
||||
interface EditHighlightBorderProps {
|
||||
@@ -46,7 +46,7 @@ export const EditHighlightBorder = ({ product }: EditHighlightBorderProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
/* return (
|
||||
<div className="flex min-h-full w-full">
|
||||
<div className="flex w-1/2 flex-col px-6 py-5">
|
||||
<div className="mb-6 flex items-center space-x-2">
|
||||
@@ -92,4 +92,54 @@ export const EditHighlightBorder = ({ product }: EditHighlightBorderProps) => {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}; */
|
||||
|
||||
return (
|
||||
<div className="flex min-h-full w-full flex-col md:flex-row">
|
||||
<div className="flex w-full flex-col px-6 py-5 md:w-1/2">
|
||||
<div className="mb-6 flex items-center space-x-2">
|
||||
<Switch id="highlightBorder" checked={showHighlightBorder} onCheckedChange={handleSwitch} />
|
||||
<h2 className="text-sm font-medium text-slate-800">Show highlight border</h2>
|
||||
</div>
|
||||
|
||||
{showHighlightBorder && color ? (
|
||||
<>
|
||||
<Label htmlFor="brandcolor">Color (HEX)</Label>
|
||||
<ColorPicker color={color} onChange={setColor} />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<Button
|
||||
variant="darkCTA"
|
||||
className="mt-4 flex max-w-[80px] items-center justify-center"
|
||||
loading={updatingBorder}
|
||||
onClick={handleUpdateHighlightBorder}>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex w-full flex-col items-center justify-center gap-4 bg-slate-200 px-6 py-5 md:mt-0 md:w-1/2">
|
||||
<h3 className="text-slate-500">Preview</h3>
|
||||
<div
|
||||
className={cn("flex flex-col gap-4 rounded-lg border-2 bg-white p-5")}
|
||||
{...(showHighlightBorder &&
|
||||
color && {
|
||||
style: {
|
||||
borderColor: color,
|
||||
},
|
||||
})}>
|
||||
<h3 className="text-sm font-semibold text-slate-800">How easy was it for you to do this?</h3>
|
||||
<div className="grid grid-cols-5 rounded-xl border border-slate-400">
|
||||
{[1, 2, 3, 4, 5].map((num) => (
|
||||
<div
|
||||
key={num}
|
||||
className="flex justify-center border-r border-slate-400 px-3 py-2 last:border-r-0 lg:px-6 lg:py-5">
|
||||
<span className="text-sm font-medium">{num}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import ShareInviteModal from "@/app/(app)/environments/[environmentId]/settings/members/ShareInviteModal";
|
||||
import TransferOwnershipModal from "@/app/(app)/environments/[environmentId]/settings/members/TransferOwnershipModal";
|
||||
import CustomDialog from "@/components/shared/CustomDialog";
|
||||
import DeleteDialog from "@/components/shared/DeleteDialog";
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import CreateTeamModal from "@/components/team/CreateTeamModal";
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
updateMemberRole,
|
||||
useMembers,
|
||||
} from "@/lib/members";
|
||||
import { useMemberships } from "@/lib/memberships";
|
||||
import { useProfile } from "@/lib/profile";
|
||||
import { capitalizeFirstLetter } from "@/lib/utils";
|
||||
import {
|
||||
@@ -35,12 +37,10 @@ import {
|
||||
} from "@formbricks/ui";
|
||||
import { ChevronDownIcon } from "@heroicons/react/20/solid";
|
||||
import { PaperAirplaneIcon, ShareIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import AddMemberModal from "./AddMemberModal";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useMemberships } from "@/lib/memberships";
|
||||
import CustomDialog from "@/components/shared/CustomDialog";
|
||||
|
||||
type EditMembershipsProps = {
|
||||
environmentId: string;
|
||||
@@ -273,7 +273,7 @@ export function EditMemberships({ environmentId }: EditMembershipsProps) {
|
||||
)}
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="mr-2"
|
||||
className="mr-2 hidden sm:inline-flex"
|
||||
onClick={() => {
|
||||
setCreateTeamModalOpen(true);
|
||||
}}>
|
||||
@@ -294,24 +294,26 @@ export function EditMemberships({ environmentId }: EditMembershipsProps) {
|
||||
<div className="col-span-2"></div>
|
||||
<div className="col-span-5">Fullname</div>
|
||||
<div className="col-span-5">Email</div>
|
||||
<div className="col-span-3">Role</div>
|
||||
<div className="col-span-5"></div>
|
||||
<div className="hidden sm:col-span-3 sm:block">Role</div>
|
||||
<div className="hidden sm:col-span-5 sm:block"></div>
|
||||
</div>
|
||||
<div className="grid-cols-20">
|
||||
{[...team.members, ...team.invitees].map((member) => (
|
||||
<div
|
||||
className="grid-cols-20 grid h-auto w-full content-center rounded-lg p-0.5 py-2 text-left text-sm text-slate-900"
|
||||
key={member.email}>
|
||||
<div className="h-58 col-span-2 pl-4">
|
||||
<ProfileAvatar userId={member.userId || member.email} />
|
||||
<div className="h-58 col-span-2 pl-4 ">
|
||||
<div className="hidden sm:block">
|
||||
<ProfileAvatar userId={member.userId || member.email} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="ph-no-capture col-span-5 flex flex-col justify-center break-all">
|
||||
<p>{member.name}</p>
|
||||
</div>
|
||||
<div className="ph-no-capture col-span-5 flex flex-col justify-center break-all">
|
||||
<div className="ph-no-capture col-span-5 flex flex-col justify-center break-all">
|
||||
{member.email}
|
||||
</div>
|
||||
<div className="ph-no-capture col-span-3 flex flex-col items-start justify-center break-all">
|
||||
<div className="ph-no-capture col-span-3 hidden flex-col items-start justify-center break-all sm:flex">
|
||||
<RoleElement
|
||||
isAdminOrOwner={isAdminOrOwner}
|
||||
memberRole={member.role}
|
||||
@@ -325,7 +327,7 @@ export function EditMemberships({ environmentId }: EditMembershipsProps) {
|
||||
currentUserRole={role}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-5 flex items-center justify-end gap-x-4 pr-4">
|
||||
<div className="col-span-5 ml-48 hidden items-center justify-end gap-x-2 pr-4 sm:ml-0 sm:gap-x-4 lg:flex">
|
||||
{!member.accepted &&
|
||||
(isExpired(member) ? (
|
||||
<Badge className="mr-2" type="gray" text="Expired" size="tiny" />
|
||||
|
||||
@@ -22,20 +22,21 @@ export default function EditAlerts({ memberships, user, environmentId }: EditAle
|
||||
<p className="text-slate-800">{membership.team.name}</p>
|
||||
</div>
|
||||
<div className="mb-6 rounded-lg border border-slate-200">
|
||||
<div className="grid h-12 grid-cols-4 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
|
||||
<div className="col-span-2">Survey</div>
|
||||
<div className="col-span-1">Product</div>
|
||||
<div className="grid h-12 grid-cols-3 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
|
||||
<div className="col-span-2 flex items-center">Survey</div>
|
||||
<TooltipProvider delayDuration={50}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="col-span-1 cursor-default text-center">
|
||||
Every Response <QuestionMarkCircleIcon className="mb-1 inline h-4 w-4 text-slate-500" />
|
||||
<div className="col-span-1 flex cursor-default items-center justify-center">
|
||||
<span className="">Every Response</span>
|
||||
<QuestionMarkCircleIcon className="h-4 w-4 flex-shrink-0 text-slate-500" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Sends complete responses, no partials.</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
|
||||
{membership.team.products.some((product) =>
|
||||
product.environments.some((environment) => environment.surveys.length > 0)
|
||||
) ? (
|
||||
@@ -46,13 +47,11 @@ export default function EditAlerts({ memberships, user, environmentId }: EditAle
|
||||
<div key={environment.id}>
|
||||
{environment.surveys.map((survey) => (
|
||||
<div
|
||||
className="grid h-auto w-full cursor-pointer grid-cols-4 place-content-center rounded-lg px-2 py-2 text-left text-sm text-slate-900 hover:bg-slate-50"
|
||||
className="grid h-auto w-full cursor-pointer grid-cols-3 place-content-center rounded-lg px-2 py-2 text-left text-sm text-slate-900 hover:bg-slate-50"
|
||||
key={survey.name}>
|
||||
<div className=" col-span-2 flex items-center ">
|
||||
<p className="text-slate-800">{survey.name}</p>
|
||||
</div>
|
||||
<div className="col-span-1 flex flex-col justify-center break-all">
|
||||
{product?.name}
|
||||
<div className="col-span-2 text-left">
|
||||
<div className="font-medium text-slate-900">{survey.name}</div>
|
||||
<div className="text-xs text-slate-400">{product.name}</div>
|
||||
</div>
|
||||
<div className="col-span-1 text-center">
|
||||
<NotificationSwitch
|
||||
|
||||
@@ -21,17 +21,17 @@ export default function EditWeeklySummary({ memberships, user, environmentId }:
|
||||
<p className="text-slate-800">{membership.team.name}</p>
|
||||
</div>
|
||||
<div className="mb-6 rounded-lg border border-slate-200">
|
||||
<div className="grid h-12 grid-cols-2 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
|
||||
<div>Product</div>
|
||||
<div className="cursor-default pr-12 text-right">Weekly Summary</div>
|
||||
<div className="grid h-12 grid-cols-3 content-center rounded-t-lg bg-slate-100 px-4 text-left text-sm font-semibold text-slate-900">
|
||||
<div className="col-span-2">Product</div>
|
||||
<div className="col-span-1 text-center">Weekly Summary</div>
|
||||
</div>
|
||||
<div className="grid-cols-8 space-y-1 p-2">
|
||||
<div className="space-y-1 p-2">
|
||||
{membership.team.products.map((product) => (
|
||||
<div
|
||||
className="grid h-auto w-full cursor-pointer grid-cols-2 place-content-center rounded-lg px-2 py-2 text-left text-sm text-slate-900 hover:bg-slate-50"
|
||||
className="grid h-auto w-full cursor-pointer grid-cols-3 place-content-center justify-center rounded-lg px-2 py-2 text-left text-sm text-slate-900 hover:bg-slate-50"
|
||||
key={product.id}>
|
||||
<div>{product?.name}</div>
|
||||
<div className="mr-20 flex justify-end">
|
||||
<div className="col-span-2">{product?.name}</div>
|
||||
<div className="col-span-1 flex items-center justify-center">
|
||||
<NotificationSwitch
|
||||
surveyOrProductId={product.id}
|
||||
userId={user.id}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import { useEnvironment } from "@/lib/environments/environments";
|
||||
import { ErrorComponent } from "@formbricks/ui";
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/solid";
|
||||
import { LightBulbIcon } from "@heroicons/react/24/solid";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function EnvironmentNotice({ environmentId }: { environmentId: string }) {
|
||||
@@ -26,14 +26,14 @@ export default function EnvironmentNotice({ environmentId }: { environmentId: st
|
||||
return (
|
||||
<div>
|
||||
{environment.type === "production" && !environment.widgetSetupCompleted && (
|
||||
<div className="flex items-center rounded-lg border border-amber-100 bg-amber-50 p-4 text-slate-900 shadow-sm">
|
||||
<ExclamationTriangleIcon className="mr-3 h-6 w-6 text-amber-700" />
|
||||
You're currently in the Production environment.
|
||||
<a
|
||||
onClick={() => changeEnvironment("development")}
|
||||
className="ml-1 cursor-pointer font-medium underline">
|
||||
Set up Development environment?
|
||||
</a>
|
||||
<div className="flex items-center space-y-3 rounded-lg border border-blue-100 bg-blue-50 p-4 text-sm text-blue-900 shadow-sm md:space-y-0 md:text-base">
|
||||
<LightBulbIcon className="mr-3 h-6 w-6 text-blue-400" />
|
||||
<p>
|
||||
You're currently in the Production environment.
|
||||
<a onClick={() => changeEnvironment("development")} className="ml-1 cursor-pointer underline">
|
||||
Switch to Development environment.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import { Confetti } from "@formbricks/ui";
|
||||
import { useEnvironment } from "@/lib/environments/environments";
|
||||
import { useEnvironmentMutation } from "@/lib/environments/mutateEnvironments";
|
||||
import { useEvents } from "@/lib/events/events";
|
||||
import { timeSince } from "@formbricks/lib/time";
|
||||
import { Confetti, ErrorComponent } from "@formbricks/ui";
|
||||
import { ArrowDownIcon, CheckIcon, ExclamationTriangleIcon } from "@heroicons/react/24/solid";
|
||||
import clsx from "clsx";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { ErrorComponent } from "@formbricks/ui";
|
||||
|
||||
interface WidgetStatusIndicatorProps {
|
||||
environmentId: string;
|
||||
@@ -81,7 +80,7 @@ export default function WidgetStatusIndicator({ environmentId, type }: WidgetSta
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex flex-col items-center justify-center space-y-2 rounded-lg py-6",
|
||||
"flex flex-col items-center justify-center space-y-2 rounded-lg py-6 text-center",
|
||||
status === "notImplemented" && "bg-slate-100",
|
||||
status === "running" && "bg-green-100",
|
||||
status === "issue" && "bg-amber-100"
|
||||
@@ -95,7 +94,7 @@ export default function WidgetStatusIndicator({ environmentId, type }: WidgetSta
|
||||
)}>
|
||||
<currentStatus.icon />
|
||||
</div>
|
||||
<p className="text-xl font-bold text-slate-800">{currentStatus.title}</p>
|
||||
<p className="text-md font-bold text-slate-800 md:text-xl">{currentStatus.title}</p>
|
||||
<p className="text-sm text-slate-700">
|
||||
{currentStatus.subtitle}{" "}
|
||||
{status !== "notImplemented" && <span>{timeSince(events[0].createdAt)}</span>}
|
||||
|
||||
Reference in New Issue
Block a user