Skip to content

Commit

Permalink
Merge pull request #13 from NIAEFEUP/feature/adapt-countdown
Browse files Browse the repository at this point in the history
Feature/adapt countdown
  • Loading branch information
limwa authored Dec 27, 2024
2 parents f0c7808 + 6b69715 commit 30a883e
Show file tree
Hide file tree
Showing 15 changed files with 397 additions and 362 deletions.
8 changes: 5 additions & 3 deletions website/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ LOG_LEVEL=info
APP_KEY=
NODE_ENV=development
SESSION_DRIVER=cookie

FROM_EMAIL=
SMTP_HOST=localhost
SMTP_PORT=1025
MAILGUN_API_KEY=
MAILGUN_DOMAIN=
FROM_EMAIL=

VITE_TZ=Europe/Lisbon
VITE_EVENT_COUNTDOWN_DATE=2025-04-11
119 changes: 119 additions & 0 deletions website/inertia/components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from "react";

import { Link } from "@inertiajs/react";

/*
import { Menu } from "lucide-react";
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
} from "./ui/navigation-menu";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "./ui/dropdown-menu";
import { Button } from "./ui/button";
type PageRoute = {
href: string;
title: string;
};
*/

export default function NavBar() {
/*
const navButtonStyle =
"font-space-grotesk uppercase group inline-flex h-9 w-max items-center justify-center text-base font-bold text-enei-beige focus:outline-none disabled:pointer-events-none";
const navLoginStyle =
"font-space-grotesk group inline-flex h-10 px-6 rounded-md w-max items-center justify-center text-base font-bold bg-enei-beige text-enei-blue focus:outline-none disabled:pointer-events-none";
const routes: PageRoute[] = [{
href: "/",
title: "Programa",
}, {
href: "/",
title: "Loja",
}, {
href: "/",
title: "Equipa",
}];
*/

return (
<>
<nav className="py-5 px-6 sm:px-12 md:px-24 lg:px-36 flex flex-row justify-between items-center flex-grow md:flex-grow-0">
<Link href="/">
<img
className="w-28 max-md:w-24"
src="/images/logo-white.svg"
alt="Logótipo da SINF"
/>
</Link>
{
/*
<NavigationMenu className="hidden sm:block">
<NavigationMenuList className="gap-5">
{routes.map(function (route, _) {
return (
<NavigationMenuItem>
<Link href={route.href}>
<NavigationMenuLink className={navButtonStyle}>
{route.title}
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
);
})}
<NavigationMenuItem>
<Link href="/">
<NavigationMenuLink className={navLoginStyle}>
Login
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
<DropdownMenu>
<DropdownMenuTrigger asChild className="sm:hidden">
<Button
variant="outline"
size="icon"
className="border border-input bg-enei-beige shadow-sm text-enei-blue hover:bg-enei-beige hover:text-enei-blue"
>
<Menu />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 bg-enei-beige border-enei-blue">
<DropdownMenuGroup>
{routes.map(function (route, _) {
return (
<Link
href={route.href}
className="uppercase font-space-grotesk font-semibold text-enei-blue"
>
<DropdownMenuItem className="focus:bg-enei-beige focus:text-enei-blue">
{route.title}
</DropdownMenuItem>
</Link>
);
})}
</DropdownMenuGroup>
<DropdownMenuSeparator className="bg-enei-blue" />
<DropdownMenuItem className="font-space-grotesk font-semibold text-enei-blue focus:bg-enei-beige focus:text-enei-blue">
Login
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
*/
}
</nav>
</>
);
}
5 changes: 5 additions & 0 deletions website/inertia/css/app.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
Expand Down Expand Up @@ -37,6 +38,7 @@
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
Expand Down Expand Up @@ -72,10 +74,13 @@
--sidebar-ring: 217.2 91.2% 59.8%;
}
}

@layer base {

* {
@apply border-border;
}

body {
@apply bg-background text-foreground;
}
Expand Down
16 changes: 16 additions & 0 deletions website/inertia/hooks/use_countdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect, useState } from 'react'
import { createCountdown, CreateCountdownOptions, TimeLeft } from '~/lib/countdown'

export function useCountdown({
utcTarget,
resolution = 1000,
}: Omit<CreateCountdownOptions, 'onChange'>) {
const [timeLeft, setTimeLeft] = useState<TimeLeft | null>(null)

useEffect(() => {
const countdown = createCountdown({ utcTarget, onChange: setTimeLeft, resolution })
return () => countdown.abort('Countdown was unmounted')
}, [utcTarget, resolution, setTimeLeft])

return timeLeft
}
34 changes: 34 additions & 0 deletions website/inertia/layouts/applayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { ReactElement } from "react";
import { Head } from "@inertiajs/react";
import NavBar from "../components/navbar";

type Props = {
title: string;
children: ReactElement[];
className: string;
};

export default function AppLayout(
{ title, children, className }: Props,
) {
return (
<>
<style>
{`
html {
scroll-behavior: smooth;
}`}
</style>
<div className="min-h-screen flex flex-col bg-enei-beige">
<Head title={title} />
<div className="sticky left-0 right-0 top-0 z-30">
<NavBar />
</div>
<div className={"flex-1" + " " + className}>
{children}
<slot />
</div>
</div>
</>
);
}
69 changes: 69 additions & 0 deletions website/inertia/lib/countdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
export type TimeLeft = {
days: number
hours: number
minutes: number
seconds: number
miliseconds: number
}

const milisInSecond = 1000
const milisInMinute = 60 * milisInSecond
const milisInHour = 60 * milisInMinute
const milisInDay = 24 * milisInHour

function milisecondsToTimeLeft(miliseconds: number): TimeLeft {
const days = Math.floor(miliseconds / milisInDay)
miliseconds -= days * milisInDay

const hours = Math.floor(miliseconds / milisInHour)
miliseconds -= hours * milisInHour

const minutes = Math.floor(miliseconds / milisInMinute)
miliseconds -= minutes * milisInMinute

const seconds = Math.floor(miliseconds / 1000)
miliseconds -= seconds * 1000

return {
days,
hours,
minutes,
seconds,
miliseconds,
}
}

export type CreateCountdownOptions = {
utcTarget: number
resolution?: number
onChange: (timeLeft: TimeLeft) => void
}

export function createCountdown({
utcTarget,
onChange,
resolution = 1000,
}: CreateCountdownOptions) {
const controller = new AbortController()

function tick() {
const now = Date.now()
const distance = Math.max(0, utcTarget - now)

if (distance <= 0) {
controller.abort('Countdown has ended')
}

onChange(milisecondsToTimeLeft(distance))
}

const id = setInterval(() => tick(), resolution)
controller.signal.addEventListener('abort', () => clearInterval(id))

// tick once so listeners are up-to-date
tick()

return {
abort: controller.abort,
}
}
2 changes: 2 additions & 0 deletions website/inertia/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export type ClassName = string | ClassValue | ClassValue[]

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Loading

0 comments on commit 30a883e

Please sign in to comment.