Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not merge/signal london #194

Closed
wants to merge 17 commits into from
Closed
2 changes: 1 addition & 1 deletion __tests__/scripts/whatsappTemplates.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getHelpPrivacyTemplate } from "@/scripts/buildContentTemplates";
import { describe, expect, test } from "vitest";
import { getHelpPrivacyTemplate } from "@/scripts/getTemplates";

describe("getHelpPrivacyTemplate", () => {
test("should return an object with the correct structure", () => {
Expand Down
1 change: 1 addition & 0 deletions public/channel-icons/sms.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/channel-icons/whatsapp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
214 changes: 214 additions & 0 deletions src/app/(layout-free)/event/[slug]/kiosk/kiosk-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
"use client";

import { Button } from "@/components/ui/button";
import { useState } from "react";
import { Selection } from "../../../../../components/menu-select";

import { MenuItem as MenuItemInterface } from "@/config/menus";
import MultiSelect from "@/components/ui/multi-select";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { useToast } from "@/components/ui/use-toast";
import MenuItem from "@/app/(layout-free)/event/[slug]/menu/menu-item";
import { Checkbox } from "@/components/ui/checkbox";
import { MessageCircleMoreIcon, MessageSquareIcon } from "lucide-react";

export default function OrderForm({
selection,
eventSlug,
}: {
selection: Selection;
eventSlug: string;
}) {
const [pending, setPending] = useState(false);

const { toast } = useToast();
const [order, setOrder] = useState<{
item: MenuItemInterface;
phone: string;
event: string;
modifiers: any[];
whatsapp: boolean;
agreed: boolean;
}>({
item: {
title: "",
shortTitle: "",
description: "",
},
event: eventSlug,
phone: "",
modifiers: [],
whatsapp: true,
agreed: false,
});

const incomplete =
!order.item || !order.phone || !order.agreed || !order.item?.title;

return (
<div className="text-3xl flex flex-col space-y-8 w-full my-auto">
<div className={`grid grid-cols-3 gap-6 select-none`}>
{selection?.items.map((item: MenuItemInterface, index: Number) => (
<div
key={`${item.title}-${index}`}
onClick={() => {
setOrder({ ...order, item: item });
}}
className={`px-10 pb-8 rounded-lg mb-2 ${item.title === order.item?.title ? "bg-gray-400" : "bg-gray-200"} `}
// {/* Use these parameters to adapt to a different screen size */}
// and also font size and space-y-8 above
>
<MenuItem
title={item.title}
shortTitle={item.shortTitle}
description={item.description}
/>
</div>
))}
</div>
{selection.modifiers.length > 0 && (
<>
<Label className="text-3xl" htmlFor="modifiers">
Would you like any extras with your order?
</Label>
<MultiSelect
placeholder=""
className="w-full"
value={order.modifiers}
id="modifiers"
options={selection.modifiers.map((m) => {
return { label: m, value: m };
})}
onChange={(selected) => {
//@ts-ignore
setOrder({ ...order, modifiers: selected });
}}
/>
</>
)}
<Label className="text-3xl" aria-required htmlFor="phone">
Phone number
</Label>
<div className="flex items-center space-x-2">
<Input
id="phone"
className="text-3xl w-4/5"
type="tel"
value={order.phone}
required
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setOrder({ ...order, phone: e.target.value })
}
/>
<span
className="text-2xl whitespace-nowrap cursor-pointer"
onClick={() => {
setOrder({ ...order, whatsapp: !order.whatsapp });
}}
>
{order.whatsapp ? "via WhatsApp" : "via SMS"}
</span>

<button
title="Use WhatsApp"
className={`rounded-lg p-2 bg-green-500 hover:bg-green-300`}
onClick={() => {
setOrder({ ...order, whatsapp: !order.whatsapp });
}}
>
{order.whatsapp ? (
<img
src="/channel-icons/whatsapp.svg"
className={`h-10 w-10 text-white`}
/>
) : (
<img
src="/channel-icons/sms.svg"
className={`h-10 w-10 text-white`}
/>
)}
</button>
</div>

<div className="flex items-center space-x-2 ">
<Checkbox
id="privacy"
checked={order.agreed}
className="w-10 h-10 mr-5"
onCheckedChange={(checked: boolean) => {
setOrder({ ...order, agreed: checked });
}}
/>
<label
htmlFor="privacy"
className="font-medium text-2xl leading-none "
>
I consent that Twilio can reach out to me with regard to my coffee
order. All data will be deleted after the event.
</label>
</div>

<Button
onClick={(e) => {
setPending(true);

const body = {
phone: order?.phone,
whatsapp: order?.whatsapp,
item: order.item,
event: eventSlug,
};

if (order?.modifiers?.length > 0) {
//@ts-ignore
body.modifiers = order?.modifiers.map(
//@ts-ignore
(modifier) => modifier?.value,
);
}

fetch("/api/kioskOrder", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}).then((res) => {
setPending(false);
if (res.ok) {
setOrder({
item: {
title: "",
shortTitle: "",
description: "",
},
event: eventSlug,
phone: "",
modifiers: [],
agreed: false,
whatsapp: true,
});

toast({
title: "Order Created",
// @ts-ignore
description: `Your order for a ${order.item.title} has been created. Check your phone for the confirmation.`,
});
} else {
toast({
title: "Error",
description: res?.statusText + ". Please try again and let our staff know if the problem persists.",
});
}
});
}}
type="submit"
disabled={pending || incomplete}
className="text-3XL uppercase p-8 w-full bg-slate-300 hover:bg-slate-400 "
>
{pending ? "Ordering..." : "Create Order"}
</Button>
</div>
);
}
14 changes: 14 additions & 0 deletions src/app/(layout-free)/event/[slug]/kiosk/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Header from "../menu/header";

import { Toaster } from "@/components/ui/toaster";

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen flex flex-col">
<Header number="ABC" />
<Toaster />
<main className="px-24 pt-16">{children}</main>
{/* Use these parameters to adapt to a different screen size */}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Privilege } from "@/middleware";
import { cookies } from "next/headers";
import OrderForm from "./order-form";
import OrderForm from "./kiosk-form";
import { getSyncService } from "@/lib/twilio";

export default async function KioskPage(props: {
Expand Down Expand Up @@ -28,18 +28,19 @@ export default async function KioskPage(props: {
const event = items.find((item) => item.data.slug === params.slug);

return (
<main className="p-4 md:p-6 lg:p-8 space-y-8 flex-1">
<h1 className="text-3xl font-bold">Kiosk</h1>
<div className="p-4 space-y-8 flex-1">
<p className="text-6xl font-bold">Welcome to SIGNAL London!</p>
<p className="text-4xl">
Order your coffee here and pick it up at the barista station.
</p>
{hasPermissions && (
<OrderForm
eventSlug={params.slug}
askForSender={true}
showToast={true}
selection={event?.data.selection}
/>
)}
{!hasPermissions && <p>Unauthorized</p>}
</main>
{!hasPermissions && <p className="text-4xl">Unauthorized</p>}
</div>
);
} catch (e: any) {
console.error(e);
Expand Down
4 changes: 2 additions & 2 deletions src/app/(layout-free)/event/[slug]/menu/menu-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function MenuItem({
}) {
const IconComponent = iconMap[shortTitle];
return (
<div className="flex flex-col">
<div className="flex flex-col cursor-pointer">
{IconComponent ? (
<IconComponent
width="8rem"
Expand All @@ -31,7 +31,7 @@ export default function MenuItem({
)}
<div className="text-center">
<h3 className="font-semibold">{title}</h3>
<p className="text-sm text-gray-500 dark:text-gray-400">
<p className="text-sm mt-2 text-gray-800 ">
{description}
</p>
</div>
Expand Down
10 changes: 8 additions & 2 deletions src/app/(master-layout)/configuration/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ function ConfigPage() {
});
}}
>
<MessageSquareIcon className={`h-6 w-6 text-white`} />
<img
src="/channel-icons/sms.svg"
className={`h-6 w-6 text-white`}
/>
</button>
<button
title={
Expand All @@ -68,7 +71,10 @@ function ConfigPage() {
});
}}
>
<MessageCircleMoreIcon className={`h-6 w-6 text-white`} />
<img
src="/channel-icons/whatsapp.svg"
className={`h-6 w-6 text-white`}
/>
</button>
</div>
))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PopoverContent } from "@/components/ui/popover";
import { Selection } from "../../../../../components/menu-select";
import OrderForm from "../kiosk/order-form";
import OrderForm from "./order-form";

export default function CustomOrderPopoverContent({
selection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function HeaderControls({
getCookie("privilege") as Privilege,
);

if(!isPriviledged) return null;
if (!isPriviledged) return null;

return (
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export default function OrderForm({
disabled={pending}
className="w-full bg-slate-300 hover:bg-slate-400 "
>
{pending ? "Creating..." : "Create Order"}
{pending ? "Ordering..." : "Create Order"}
</Button>
</form>
);
Expand Down
Loading
Loading