Fixed dismiss on toggle + implemented switch component
This commit is contained in:
parent
5d5a90d4f8
commit
4759aed51d
4 changed files with 84 additions and 26 deletions
41
components/ui/Switch.tsx
Normal file
41
components/ui/Switch.tsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import * as PrimitiveSwitch from "@radix-ui/react-switch";
|
||||||
|
import * as Label from "@radix-ui/react-label";
|
||||||
|
|
||||||
|
function classNames(...classes) {
|
||||||
|
return classes.filter(Boolean).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Switch(props) {
|
||||||
|
const { label, onCheckedChange, ...primitiveProps } = props;
|
||||||
|
const [checked, setChecked] = useState(props.defaultChecked || false);
|
||||||
|
|
||||||
|
const onPrimitiveCheckedChange = (change: boolean) => {
|
||||||
|
if (onCheckedChange) {
|
||||||
|
onCheckedChange(change);
|
||||||
|
}
|
||||||
|
setChecked(change);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center h-[20px]">
|
||||||
|
<PrimitiveSwitch.Root
|
||||||
|
className={classNames(checked ? "bg-gray-900" : "bg-gray-400", "rounded-sm w-[36px] p-0.5 h-[20px]")}
|
||||||
|
checked={checked}
|
||||||
|
onCheckedChange={onPrimitiveCheckedChange}
|
||||||
|
{...primitiveProps}>
|
||||||
|
<PrimitiveSwitch.Thumb
|
||||||
|
className={classNames(
|
||||||
|
"bg-white w-[16px] h-[16px] block transition-transform",
|
||||||
|
checked ? "translate-x-[16px]" : "translate-x-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</PrimitiveSwitch.Root>
|
||||||
|
{label && (
|
||||||
|
<Label.Root className="text-neutral-700 align-text-top ml-3 font-medium cursor-pointer">
|
||||||
|
{label}
|
||||||
|
</Label.Root>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
"@radix-ui/react-collapsible": "^0.0.16",
|
"@radix-ui/react-collapsible": "^0.0.16",
|
||||||
"@radix-ui/react-dialog": "^0.0.19",
|
"@radix-ui/react-dialog": "^0.0.19",
|
||||||
"@radix-ui/react-slot": "^0.0.12",
|
"@radix-ui/react-slot": "^0.0.12",
|
||||||
|
"@radix-ui/react-switch": "^0.0.15",
|
||||||
"@radix-ui/react-tooltip": "^0.0.21",
|
"@radix-ui/react-tooltip": "^0.0.21",
|
||||||
"@tailwindcss/forms": "^0.2.1",
|
"@tailwindcss/forms": "^0.2.1",
|
||||||
"async": "^3.2.0",
|
"async": "^3.2.0",
|
||||||
|
|
|
@ -6,10 +6,9 @@ import { useEffect, useState } from "react";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import { CheckCircleIcon, ChevronRightIcon, PlusIcon, XCircleIcon } from "@heroicons/react/solid";
|
import { CheckCircleIcon, ChevronRightIcon, PlusIcon, XCircleIcon } from "@heroicons/react/solid";
|
||||||
import { InformationCircleIcon } from "@heroicons/react/outline";
|
import { InformationCircleIcon } from "@heroicons/react/outline";
|
||||||
import { Switch } from "@headlessui/react";
|
|
||||||
import Loader from "@components/Loader";
|
|
||||||
import classNames from "@lib/classNames";
|
|
||||||
import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTrigger } from "@components/Dialog";
|
import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTrigger } from "@components/Dialog";
|
||||||
|
import Switch from "@components/ui/Switch";
|
||||||
|
import Loader from "@components/Loader";
|
||||||
|
|
||||||
export default function IntegrationHome({ integrations }) {
|
export default function IntegrationHome({ integrations }) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
@ -32,17 +31,15 @@ export default function IntegrationHome({ integrations }) {
|
||||||
|
|
||||||
function calendarSelectionHandler(calendar) {
|
function calendarSelectionHandler(calendar) {
|
||||||
return (selected) => {
|
return (selected) => {
|
||||||
const cals = [...selectableCalendars];
|
const i = selectableCalendars.findIndex((c) => c.externalId === calendar.externalId);
|
||||||
const i = cals.findIndex((c) => c.externalId === calendar.externalId);
|
selectableCalendars[i].selected = selected;
|
||||||
cals[i].selected = selected;
|
|
||||||
setSelectableCalendars(cals);
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
fetch("api/availability/calendar", {
|
fetch("api/availability/calendar", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(cals[i]),
|
body: JSON.stringify(selectableCalendars[i]),
|
||||||
}).then((response) => response.json());
|
}).then((response) => response.json());
|
||||||
} else {
|
} else {
|
||||||
fetch("api/availability/calendar", {
|
fetch("api/availability/calendar", {
|
||||||
|
@ -50,7 +47,7 @@ export default function IntegrationHome({ integrations }) {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(cals[i]),
|
body: JSON.stringify(selectableCalendars[i]),
|
||||||
}).then((response) => response.json());
|
}).then((response) => response.json());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -67,6 +64,10 @@ export default function IntegrationHome({ integrations }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCloseSelectCalendar() {
|
||||||
|
setSelectableCalendars([...selectableCalendars]);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(loadCalendars, [integrations]);
|
useEffect(loadCalendars, [integrations]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -116,7 +117,7 @@ export default function IntegrationHome({ integrations }) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const SelectCalendarDialog = () => (
|
const SelectCalendarDialog = () => (
|
||||||
<Dialog>
|
<Dialog onOpenChange={(open) => !open && onCloseSelectCalendar()}>
|
||||||
<DialogTrigger className="py-2 px-4 mt-6 border border-transparent rounded-sm shadow-sm text-sm font-medium text-white bg-neutral-900 hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900">
|
<DialogTrigger className="py-2 px-4 mt-6 border border-transparent rounded-sm shadow-sm text-sm font-medium text-white bg-neutral-900 hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900">
|
||||||
Select calendars
|
Select calendars
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
@ -142,21 +143,9 @@ export default function IntegrationHome({ integrations }) {
|
||||||
</div>
|
</div>
|
||||||
<div className="w-2/12 text-right pt-3">
|
<div className="w-2/12 text-right pt-3">
|
||||||
<Switch
|
<Switch
|
||||||
checked={calendar.selected}
|
defaultChecked={calendar.selected}
|
||||||
onChange={calendarSelectionHandler(calendar)}
|
onCheckedChange={calendarSelectionHandler(calendar)}
|
||||||
className={classNames(
|
|
||||||
calendar.selected ? "bg-neutral-900" : "bg-gray-200",
|
|
||||||
"relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500"
|
|
||||||
)}>
|
|
||||||
<span className="sr-only">Select calendar</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={classNames(
|
|
||||||
calendar.selected ? "translate-x-5" : "translate-x-0",
|
|
||||||
"pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</Switch>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -185,7 +174,7 @@ export default function IntegrationHome({ integrations }) {
|
||||||
{integrations
|
{integrations
|
||||||
.filter((ig) => ig.credential)
|
.filter((ig) => ig.credential)
|
||||||
.map((ig) => (
|
.map((ig) => (
|
||||||
<li key={ig.id}>
|
<li key={ig.credential.id}>
|
||||||
<Link href={"/integrations/" + ig.credential.id}>
|
<Link href={"/integrations/" + ig.credential.id}>
|
||||||
<a className="block hover:bg-gray-50">
|
<a className="block hover:bg-gray-50">
|
||||||
<div className="flex items-center px-4 py-4 sm:px-6">
|
<div className="flex items-center px-4 py-4 sm:px-6">
|
||||||
|
|
27
yarn.lock
27
yarn.lock
|
@ -867,6 +867,17 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-label@0.0.15":
|
||||||
|
version "0.0.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-0.0.15.tgz#ab70d7cd93d6ebaf2e1007cca70e9b1858bcb932"
|
||||||
|
integrity sha512-p1nM6z2rLkstfHVsqSxcDMn0eAGXkx/G5e4XIGmOCxYa/7EkOQ+lBz0+/7sk+Ut+8B37h7d0bfxnzr3ILVxJUw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-id" "0.0.6"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.13"
|
||||||
|
"@radix-ui/react-primitive" "0.0.15"
|
||||||
|
|
||||||
"@radix-ui/react-polymorphic@0.0.12":
|
"@radix-ui/react-polymorphic@0.0.12":
|
||||||
version "0.0.12"
|
version "0.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.12.tgz#bf4ae516669b68e059549538104d97322f7c876b"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.12.tgz#bf4ae516669b68e059549538104d97322f7c876b"
|
||||||
|
@ -954,6 +965,22 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-compose-refs" "0.0.5"
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
|
||||||
|
"@radix-ui/react-switch@^0.0.15":
|
||||||
|
version "0.0.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-switch/-/react-switch-0.0.15.tgz#675e0abd509ac211f6c9193fab786f17bd335de3"
|
||||||
|
integrity sha512-2f2fhxvZSb21N+Va1lV4wvyY+zgPkJoKZOiK3rEH9zAmkyQ1nIDeI6eKwipeRO9WcGMeftOZBgVQTZhWSK0Rag==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "0.0.5"
|
||||||
|
"@radix-ui/react-compose-refs" "0.0.5"
|
||||||
|
"@radix-ui/react-context" "0.0.5"
|
||||||
|
"@radix-ui/react-label" "0.0.15"
|
||||||
|
"@radix-ui/react-polymorphic" "0.0.13"
|
||||||
|
"@radix-ui/react-primitive" "0.0.15"
|
||||||
|
"@radix-ui/react-use-controllable-state" "0.0.6"
|
||||||
|
"@radix-ui/react-use-previous" "0.0.5"
|
||||||
|
"@radix-ui/react-use-size" "0.0.6"
|
||||||
|
|
||||||
"@radix-ui/react-tooltip@^0.0.21":
|
"@radix-ui/react-tooltip@^0.0.21":
|
||||||
version "0.0.21"
|
version "0.0.21"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-0.0.21.tgz#86160645cf0441fa7f465c8aaa265887cc3ff9b4"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-0.0.21.tgz#86160645cf0441fa7f465c8aaa265887cc3ff9b4"
|
||||||
|
|
Loading…
Reference in a new issue