Skip to content

Commit

Permalink
Merge pull request #40 from SuperViz/refactor/realtime-package
Browse files Browse the repository at this point in the history
refactor: use realtime package instead of react
  • Loading branch information
vtnorton authored Nov 7, 2024
2 parents 7436391 + 6ee431b commit f27a673
Show file tree
Hide file tree
Showing 15 changed files with 291 additions and 152 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
AZURE_OPEN_AI=
NEXT_PUBLIC_USERDATA_KEY="CODECON:SUPERVIZ"
DATABASE_URL="postgres://superviz:superviz@localhost:5432/activation-app"
CLIENT_ID=
SECRET_KEY=

## Superviz developer token
NEXT_PUBLIC_DEVELOPER_KEY=""
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"dependencies": {
"@prisma/client": "^5.18.0",
"@superviz/react-sdk": "1.13.0-beta.1",
"@superviz/realtime": "^1.2.2",
"@tanstack/react-query": "^5.53.1",
"@superviz/realtime": "1.2.2",
"matter-js": "^0.20.0",
"next": "14.2.7",
"react": "^18",
Expand Down Expand Up @@ -44,4 +44,4 @@
"prisma": {
"schema": "src/prisma/schema.prisma"
}
}
}
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions src/app/api/dashboard/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NextResponse } from "next/server";

export async function GET(): Promise<NextResponse> {
try {
return await fetch(
`https://api.superviz.com/realtime/participants/game`,
{
method: "GET",
headers: {
secret: process.env.SECRET_KEY as string,
client_id: process.env.CLIENT_ID as string,
cache: "no-store",
},
}
)
.then((res) => {
return res.json();
})
.then((res) => {
return NextResponse.json(res.map((user: any) => user.id));
})
.catch((err) => {
return NextResponse.json([]);
});
} catch (error) {

return NextResponse.json(
{},
{
status: 500,
statusText: "Internal Server Error",
}
);
}
}

export const fetchCache = "force-no-store";
export const revalidate = 0;
18 changes: 14 additions & 4 deletions src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import Activations from "@/components/Activations";
import UsersDashboard from "@/components/UsersDashboard";
import { activations } from "@/data/activationsData";
import { SuperVizRoomProvider } from "@superviz/react-sdk";
import { ToastContainer } from 'react-toastify';
import { v4 as uuid } from 'uuid'
import './UserDashboard.scss'
import { ToastContainer } from "react-toastify";
import { v4 as uuid } from "uuid";
import "./UserDashboard.scss";
import { useRouter } from "next/navigation";
import { useRealtime } from "@/hooks/useRealtime";

const DEVELOPER_KEY = process.env.NEXT_PUBLIC_DEVELOPER_KEY as string;
const DASHBOARD_GROUP_ID = process.env.NEXT_PUBLIC_DASHBOARD_GROUP_ID as string;
Expand All @@ -25,11 +26,16 @@ const DASHBOARD_ROOM_ID = process.env.NEXT_PUBLIC_DASHBOARD_ROOM_ID as string;

export default function Dashboard() {
const router = useRouter();
const { startRealtime } = useRealtime();

const handleQRCodeClick = () => {
router.push("/giveaway");
};

React.useEffect(() => {
startRealtime(DASHBOARD_PARTICIPANT_ID, DASHBOARD_PARTICIPANT_NAME);
}, []);

return (
<SuperVizRoomProvider
developerKey={DEVELOPER_KEY}
Expand Down Expand Up @@ -62,7 +68,11 @@ export default function Dashboard() {
</p>
</div>
<button onClick={handleQRCodeClick}>
<Image src={qrcode} alt="QR Code para ativação" className="mt-[3.125rem] w-[70%] tv:mt-[6.25rem]" />
<Image
src={qrcode}
alt="QR Code para ativação"
className="mt-[3.125rem] w-[70%] tv:mt-[6.25rem]"
/>
</button>
</div>
<Image
Expand Down
111 changes: 72 additions & 39 deletions src/app/giveaway/page.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,77 @@
'use client'
"use client";

import Button from "@/components/Button";
import React, { useMemo } from "react";
import React from "react";
import { sortWinner } from "@/app/services/sortWinner";
import Image from "next/image";
import fenderImg from "../../../public/alexa-user.png";
import winnerBadge from "../../../public/winner-badge.png";
// @ts-ignore
import Confetti from 'react-confetti'
import Confetti from "react-confetti";

import './Giveaway.scss'
import "./Giveaway.scss";

enum giveAwayStatus {
UNSORTED,
SORTING,
SORTED
SORTED,
}

export default function Sorter() {
const [giveAway, setGiveAway] = React.useState(giveAwayStatus.UNSORTED)
const [giveAway, setGiveAway] = React.useState(giveAwayStatus.UNSORTED);
const [winner, setWinner] = React.useState({
email: '',
user: '',
coupon: '',
})
email: "",
user: "",
coupon: "",
});

const handleClick = async () => {
setGiveAway(giveAwayStatus.SORTING)
const response = await sortWinner()
setGiveAway(giveAwayStatus.SORTING);
const response = await sortWinner();

setWinner({
email: response.user.email,
user: response.user.name,
coupon: response.coupon.activation,
})
}
});
};

const handleVideoEnd = () => {
setGiveAway(giveAwayStatus.SORTED)

}
setGiveAway(giveAwayStatus.SORTED);
};

return (
<>
{
giveAway === giveAwayStatus.SORTED && <Confetti width={window?.innerWidth} height={window?.innerHeight} />
}
<div id="confettiReward" className={`bgTv w-full h-screen grid grid-cols-2`}>
<div className={`col-span-1 h-screen flex flex-col relative justify-center items-center`}>
<Image src="/logo-sm.svg" width={108} height={20} alt="Logo Superviz" className="w-[13.5rem] object-contain absolute top-[7.5rem] left-[7.5rem]" />
{giveAway === giveAwayStatus.SORTED && (
<Confetti width={window?.innerWidth} height={window?.innerHeight} />
)}
<div
id="confettiReward"
className={`bgTv w-full h-screen grid grid-cols-2`}
>
<div
className={`col-span-1 h-screen flex flex-col relative justify-center items-center`}
>
<Image
src="/logo-sm.svg"
width={108}
height={20}
alt="Logo Superviz"
className="w-[13.5rem] object-contain absolute top-[7.5rem] left-[7.5rem]"
/>
{giveAway !== giveAwayStatus.SORTED && (
<div className={`flex flex-col justify-center items-center giveawayButton`}>
<div
className={`flex flex-col justify-center items-center giveawayButton`}
>
<h1 className="font-black text-[12.25rem] leading-[13.5rem] mb-[10rem] text-center">
Sorteio <br />Echo Dot 5ª Geração
Sorteio <br />
Echo Dot 5ª Geração
</h1>
{giveAway === giveAwayStatus.UNSORTED && (
<Button text={`Sortear`} type={`button`}
onClick={handleClick} />
<Button
text={`Sortear`}
type={`button`}
onClick={handleClick}
/>
)}
{giveAway === giveAwayStatus.SORTING && (
<video autoPlay width={`580`} onEnded={handleVideoEnd}>
Expand All @@ -66,28 +81,46 @@ export default function Sorter() {
</div>
)}
{giveAway === giveAwayStatus.SORTED && (
<div className={`flex flex-col justify-center items-center giveaway`}>
<div
className={`flex flex-col justify-center items-center giveaway`}
>
<p className={`text-[4rem] font-bold mb-[4rem]`}>Parabéns!</p>
<Image src={winnerBadge} alt={`Badge de ganhador`} />
<div className={'flex items-center flex-col'}>
<p className={`mt-[4.5rem] text-[9.7rem] text-[#957AFF] font-black break-words max-w-[100rem] text-center`}>
<div className={"flex items-center flex-col"}>
<p
className={`mt-[4.5rem] text-[9.7rem] text-[#957AFF] font-black break-words max-w-[100rem] text-center`}
>
{`{ `}
<span id="confettiReward" className={`text-[8.75rem] text-white`}>{winner.user}</span>
<span
id="confettiReward"
className={`text-[8.75rem] text-white`}
>
{winner.user}
</span>
{` }`}
</p>
<p className={`mt-[4.5rem] text-[9.7rem] text-[#957AFF] font-black break-words max-w-[100rem] text-center`}>
<span className={`text-[2.75rem] text-white`}>{winner.email}</span>
<p
className={`mt-[4.5rem] text-[9.7rem] text-[#957AFF] font-black break-words max-w-[100rem] text-center`}
>
<span className={`text-[2.75rem] text-white`}>
{winner.email}
</span>
</p>
</div>
<p className={'font-bold text-[4rem] mt-[7.5rem]'}>🎟️ Cupom sorteado: {winner.coupon}</p>
<p className={"font-bold text-[4rem] mt-[7.5rem]"}>
🎟️ Cupom sorteado: {winner.coupon}
</p>
</div>
)}
</div>
<div className={`bg-[#957AFF] col-span-1 m-10 rounded-[4rem] relative`}>
<Image src={fenderImg} alt="Imagem de um Echo Dot 5ª Geração" className="absolute top-1 left-0 object-contain" />
<Image
src={fenderImg}
alt="Imagem de um Echo Dot 5ª Geração"
className="absolute top-1 left-0 object-contain"
/>
</div>
</div>
</>

)
}
);
}
21 changes: 11 additions & 10 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import * as React from 'react'
import * as React from "react";
import type { Metadata } from "next";
import { Roboto } from "next/font/google";
import "./globals.css";
import { RealtimeProvider } from "@/contexts/realtime-context";

const roboto = Roboto({ weight: ['400', '700', '900'], subsets: ["latin"] });
const roboto = Roboto({ weight: ["400", "700", "900"], subsets: ["latin"] });

export const metadata: Metadata = {
title: "Superviz",
description: "Generated with <3 by Superviz",
}
};

export const dynamic = "force-dynamic";

Expand All @@ -18,12 +19,12 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="pt-BR">
<body className={roboto.className}>
<main>
{children}
</main>
</body>
</html>
<RealtimeProvider>
<html lang="pt-BR">
<body className={roboto.className}>
<main>{children}</main>
</body>
</html>
</RealtimeProvider>
);
}
24 changes: 5 additions & 19 deletions src/app/services/getUserData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,11 @@ export function getUsers(): Promise<IUserResponse[]> {
.then((res) => res.data.users);
}

export function getOnlineUsersIds(): Promise<string[]> {
const ROOM_ID = process.env.NEXT_PUBLIC_DASHBOARD_ROOM_ID as string;
const DEVELOPER_KEY = process.env.NEXT_PUBLIC_DEVELOPER_KEY as string;
return fetch(
`https://nodeapi.superviz.com/realtime/participants/${ROOM_ID}/default`,
{
method: "GET",
headers: {
apiKey: DEVELOPER_KEY,
cache: "no-store",
},
}
)
.then((res) => {
return res.json();
})
.then((res) => {
return res.map((user: any) => user.id);
})
export async function getOnlineUsersIds(): Promise<string[]> {
return await fetch(`/api/dashboard`, {
method: "GET",
})
.then((res) => res.json())
.catch((err) => {
return [];
});
Expand Down
Loading

0 comments on commit f27a673

Please sign in to comment.