Skip to content

Commit

Permalink
Improved RFIDLoginDialog UI
Browse files Browse the repository at this point in the history
  • Loading branch information
ccruzkauppila committed Oct 29, 2024
1 parent 7f34629 commit ce1d2d9
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 17 deletions.
55 changes: 52 additions & 3 deletions src/components/ui/AnimatedPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import { cva } from "class-variance-authority";
import React, { type ReactNode, useImperativeHandle, useState } from "react";

import * as Dialog from "@radix-ui/react-dialog";
Expand All @@ -12,6 +13,7 @@ interface Props extends Partial<React.FC<Dialog.DialogProps>> {
TriggerComponent: ReactNode;
children: ReactNode;
ref?: React.RefObject<unknown>;
style?: "default" | "RFIDInstructions";
}

export interface PopupRefActions {
Expand All @@ -20,14 +22,60 @@ export interface PopupRefActions {
toggleContainer: () => void;
}

export const AnimatedPopup = ({ ref = React.createRef(), ...props }: Props) => {
const popupStyles = cva(
"fixed left-1/2 z-20 flex h-auto translate-y-1/2 items-center justify-center bg-neutral-50 lg:w-[60vw] xl:w-fit",
{
variants: {
style: {
default: "top-1/2 w-[90vw] rounded-2xl",
RFIDInstructions:
"top-0 w-full rounded-bl-[50%_15%] rounded-br-[50%_15%]",
},
},
},
);

const transformStyles = cva(" ", {
variants: {
style: { default: {}, RFIDInstructions: {} },
open: { true: {}, false: {} },
},
compoundVariants: [
{
style: "default",
open: true,
class: "translate(-50%, -50%)",
},
{
style: "default",
open: false,
class: "translate(-50%, 100%)",
},
{
style: "RFIDInstructions",
open: true,
class: "translate(-50%, -10%)",
},
{
style: "RFIDInstructions",
open: false,
class: "translate(-50%, -100%)",
},
],
});

export const AnimatedPopup = ({
ref = React.createRef(),
style = "default",
...props
}: Props) => {
const { TriggerComponent, children, ...restProps } = props;
const [open, setOpen] = useState<boolean>(false);
const [isAnimating, setIsAnimating] = useState<boolean>(false);
const toggleContainer = () => setOpen((prev) => !prev);

const containerAnimation = useSpring({
transform: open ? "translate(-50%, -50%)" : "translate(-50%, 100%)",
transform: transformStyles({ style, open }),
opacity: open ? 1 : 0,
onRest: () => {
if (!open && isAnimating) {
Expand Down Expand Up @@ -80,7 +128,8 @@ export const AnimatedPopup = ({ ref = React.createRef(), ...props }: Props) => {
/>
<AnimatedDialog
style={containerAnimation}
className="fixed left-1/2 top-1/2 z-20 flex h-auto w-[90vw] items-center justify-center rounded-2xl bg-neutral-50 lg:w-[60vw] xl:w-fit"
className={popupStyles({ style })}
onInteractOutside={toggleContainer}
>
{children}
</AnimatedDialog>
Expand Down
62 changes: 48 additions & 14 deletions src/components/ui/RfidLoginDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,53 @@
"use client";

import { cva } from "class-variance-authority";
import { set } from "lodash";
import { ReactNode, useEffect, useRef, useState } from "react";
import { IoIosCheckmarkCircleOutline } from "react-icons/io";
import { LuNfc } from "react-icons/lu";
import { LuSmartphoneNfc } from "react-icons/lu";
import { TiWiFi } from "react-icons/ti";

import { AnimatedPopup, PopupRefActions } from "@/components/ui/AnimatedPopup";
import { FatButton } from "@/components/ui/Buttons/FatButton";
import { rfidLoginAction } from "@/server/actions/auth/login";
import { useNfcReader } from "@/state/useNfcReader";
import { useAutoAnimate } from "@formkit/auto-animate/react";

import { ThinButton } from "./Buttons/ThinButton";

const steps = [
{
title: "Scanning...",
description:
"Please place your access card on the NFC reader on the back of the device.",
description: "Place your access card on the back of the device.",
icon: <TiWiFi />,
},
{
title: "Scan successful",
description: "Logging in...",
icon: <IoIosCheckmarkCircleOutline />,
},
{ title: "OK", description: "Read successful, logging in..." },
];

export const RfidLoginDialog = () => {
const [step, setStep] = useState(0);
const popupRef = useRef<PopupRefActions>(undefined);
const [parent] = useAutoAnimate<HTMLDivElement>({ duration: 2000 });

const reader = useNfcReader();
const scan = async () => {
console.log("scan triggered");
console.log("reader is", reader);
try {
const tagId = await reader.scanOne();
console.log("successfully scanned:", tagId);
rfidLoginAction(tagId);
setTimeout(() => {
augmentStep();
}, 1000);
//rfidLoginAction(tagId);
} catch (e) {
console.log("Failed to scan:", e);
setStep(0);
}
//augmentStep();
};
Expand Down Expand Up @@ -61,21 +77,39 @@ export const RfidLoginDialog = () => {
);

return (
<AnimatedPopup ref={popupRef} TriggerComponent={loginButton}>
<div className="flex flex-col items-center gap-12 px-12 py-12">
<h2 className="mt-6 text-4xl font-bold text-neutral-700">
{steps[step]?.title}
</h2>
<AnimatedPopup
ref={popupRef}
TriggerComponent={loginButton}
style="RFIDInstructions"
>
<div className="flex flex-col items-center gap-4 px-6 py-5 md:gap-4 md:px-24 md:py-12">
<div
className="flex w-full items-center justify-center gap-8"
ref={parent}
>
<span className="text-8xl text-primary-400">{steps[step]?.icon}</span>
<div className="flex flex-col gap-2">
<h2 className="text-3xl font-bold text-neutral-700">
{steps[step]?.title}
</h2>
<p className="text-xl text-neutral-600">
{steps[step]?.description}
</p>
</div>
</div>

<p className="text-xl">{steps[step]?.description}</p>
<p className="text-xl">Reader available: {String(reader.available)}</p>
<p className="text-xl">Reader scanning: {String(reader.scanning)}</p>
<FatButton
{/* <div className="flex w-full justify-center gap-6">
<p className="text-xl">
Reader available: {String(reader.available)}
</p>
<p className="text-xl">Reader scanning: {String(reader.scanning)}</p>
</div> */}
{/* <FatButton
buttonType="button"
text="Cancel"
intent="tertiary"
onClick={closeModal}
/>
/> */}
</div>
</AnimatedPopup>
);
Expand Down

0 comments on commit ce1d2d9

Please sign in to comment.