-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from NIAEFEUP/feature/adapt-countdown
Feature/adapt countdown
- Loading branch information
Showing
15 changed files
with
397 additions
and
362 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |
Oops, something went wrong.