Added theme switcher + optimized youtube loading + about changes

This commit is contained in:
cdricms
2025-01-31 17:28:13 +01:00
parent f7dd0c60d6
commit 90945b161d
8 changed files with 306 additions and 267 deletions

View File

@@ -21,6 +21,7 @@ import {
import Link from "next/link";
import { deleteCookie, getCookie } from "cookies-next";
import { useEffect, useState } from "react";
import { ThemeSwitcher } from "./theme-switcher";
const subMenuItemsOne = [
{
@@ -142,6 +143,7 @@ const Navbar = () => {
</div>
</div>
<div className="flex gap-2 animate-in ease-in-out">
<ThemeSwitcher />
<Button variant="outline">
{cookie ? (
<Link href="/dashboard">Compte</Link>
@@ -175,190 +177,136 @@ const Navbar = () => {
Latosa-Escrima
</span>
</div>
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="size-4" />
</Button>
</SheetTrigger>
<SheetContent className="overflow-y-auto">
<SheetHeader>
<SheetTitle>
<div className="flex items-center gap-2">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
className="w-8"
alt="logo"
/>
<span className="text-xl font-bold">
Latosa-Escrima
</span>
<div className="flex gap-2">
<ThemeSwitcher />
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="size-4" />
</Button>
</SheetTrigger>
<SheetContent className="overflow-y-auto">
<SheetHeader>
<SheetTitle>
<div className="flex items-center gap-2">
<img
src="https://shadcnblocks.com/images/block/block-1.svg"
className="w-8"
alt="logo"
/>
<span className="text-xl font-bold">
Latosa-Escrima
</span>
</div>
</SheetTitle>
</SheetHeader>
<div className="mb-8 mt-8 flex flex-col gap-4">
<Link
href="/"
className="font-semibold"
>
Accueil
</Link>
<Link
href="/planning"
className="font-semibold"
>
Planning
</Link>
<Link
href="/about"
className="font-semibold"
>
À propos
</Link>
<Link
href="/blog"
className="font-semibold"
>
Blog
</Link>
</div>
<div className="border-t pt-4">
<div className="grid grid-cols-2 justify-start">
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Press
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Contact
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Imprint
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Sitemap
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Legal
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Cookie Settings
</a>
</div>
<div className="mt-2 flex flex-col gap-3">
<Button variant="outline">
<Link href="/login">
Se connecter
</Link>
</Button>
<Button>Sign up</Button>
</div>
</SheetTitle>
</SheetHeader>
<div className="mb-8 mt-8 flex flex-col gap-4">
<Link href="/" className="font-semibold">
Accueil
</Link>
<Accordion
type="single"
collapsible
className="w-full"
>
<AccordionItem
value="products"
className="border-b-0"
>
<AccordionTrigger className="mb-4 py-0 font-semibold hover:no-underline">
Products
</AccordionTrigger>
<AccordionContent className="mt-2">
{subMenuItemsOne.map(
(item, idx) => (
<a
key={idx}
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{item.title}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
),
)}
</AccordionContent>
</AccordionItem>
<AccordionItem
value="resources"
className="border-b-0"
>
<AccordionTrigger className="py-0 font-semibold hover:no-underline">
Resources
</AccordionTrigger>
<AccordionContent className="mt-2">
{subMenuItemsTwo.map(
(item, idx) => (
<a
key={idx}
className={cn(
"flex select-none gap-4 rounded-md p-3 leading-none outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
)}
href="#"
>
{item.icon}
<div>
<div className="text-sm font-semibold">
{item.title}
</div>
<p className="text-sm leading-snug text-muted-foreground">
{
item.description
}
</p>
</div>
</a>
),
)}
</AccordionContent>
</AccordionItem>
</Accordion>
<a href="#" className="font-semibold">
Pricing
</a>
<a href="#" className="font-semibold">
Blog
</a>
</div>
<div className="border-t pt-4">
<div className="grid grid-cols-2 justify-start">
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Press
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Contact
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Imprint
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Sitemap
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Legal
</a>
<a
className={cn(
buttonVariants({
variant: "ghost",
}),
"justify-start text-muted-foreground",
)}
href="#"
>
Cookie Settings
</a>
</div>
<div className="mt-2 flex flex-col gap-3">
<Button variant="outline">
<Link href="/login">
Se connecter
</Link>
</Button>
<Button>Sign up</Button>
</div>
</div>
</SheetContent>
</Sheet>
</SheetContent>
</Sheet>
</div>
</div>
</div>
</div>

View File

@@ -1,6 +1,6 @@
"use client";
import { ApiResponse, request, useApi } from "@/hooks/use-api";
import { ApiResponse, request } from "@/hooks/use-api";
import "@schedule-x/theme-shadcn/dist/index.css";
import { useNextCalendarApp, ScheduleXCalendar } from "@schedule-x/react";
import { createEventsServicePlugin } from "@schedule-x/events-service";
@@ -26,17 +26,24 @@ import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { KeyedMutator } from "swr";
import { getCookie } from "cookies-next";
import { useTheme } from "next-themes";
const Planning: React.FC<{
events: CalendarEventExternal[];
mutate?: KeyedMutator<ApiResponse<CalendarEventExternal[]>>;
}> = ({ events, mutate }) => {
const plugins = [
createEventsServicePlugin(),
createDragAndDropPlugin(),
createResizePlugin(),
createEventRecurrencePlugin(),
];
const { resolvedTheme } = useTheme();
console.log(resolvedTheme);
const isConnected = getCookie("auth_token");
const plugins = isConnected
? [
createEventsServicePlugin(),
createDragAndDropPlugin(),
createResizePlugin(),
createEventRecurrencePlugin(),
]
: [];
const [eventSelected, setEventSelected] =
useState<CalendarEventExternal | null>(null);
const [newEvent, setNewEvent] = useState<Omit<
@@ -70,7 +77,7 @@ const Planning: React.FC<{
theme: "shadcn",
views: [createViewDay(), createViewWeek()],
defaultView: "week",
isDark: true,
isDark: resolvedTheme === "dark" ? true : false,
isResponsive: true,
locale: "fr-FR",
dayBoundaries: {
@@ -102,6 +109,10 @@ const Planning: React.FC<{
calendar?.events.getAll();
}, []);
useEffect(() => {
calendar?.setTheme(resolvedTheme === "dark" ? "dark" : "light");
}, [resolvedTheme]);
const AddButton: React.FC = () => (
<Button onClick={() => setNewEvent({})} variant="outline">
Nouveau

View File

@@ -0,0 +1,40 @@
"use client";
import * as React from "react";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export function ThemeSwitcher() {
const { setTheme } = useTheme();
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Changer le thème</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>
Clair
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Sombre
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
Système
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -0,0 +1,77 @@
"use client";
import { IYoutubeItem } from "@/interfaces/youtube";
import Image from "next/image";
import { useState } from "react";
export default function YouTubeEmbed({
video,
width = 424,
height = 238,
loadIframe = false,
autoPlay = true,
}: {
video: IYoutubeItem | string;
width?: number | "full";
height?: number | "full";
loadIframe?: boolean;
autoPlay?: boolean;
}) {
const [isIframeLoaded, setIframeLoaded] = useState(loadIframe);
const isString = typeof video === "string";
const _loadIframe = () => setIframeLoaded(true);
return (
<div
className={`relative w-${width === "full" ? width : "[" + width + "px]"} h-${height === "full" ? height : "[" + height + "px]"} cursor-pointer`}
onClick={_loadIframe}
>
{isIframeLoaded ? (
<iframe
className="rounded-md shadow-current aspect-video"
width={width === "full" ? "100%" : width}
height={height === "full" ? "100%" : height}
src={`https://www.youtube-nocookie.com/embed/${isString ? video : video.id.videoId}?rel=0&modestbranding=1&autoplay=${autoPlay ? 1 : 0}`}
title={
isString ? "YouTube video player" : video.snippet.title
}
allow="accelerometer; autoplay; encrypted-media; gyroscope"
allowFullScreen
/>
) : (
<>
{width === "full" || height === "full" ? (
<img
width="100%"
height="100%"
className="w-full h-full object-cover rounded-md shadow-current"
src={`https://img.youtube.com/vi/${isString ? video : video.id.videoId}/hqdefault.jpg`}
alt={
isString
? "YouTube video player"
: video.snippet.title
}
/>
) : (
<Image
width={width}
height={height}
className="w-full h-full object-cover rounded-md shadow-current"
src={`https://img.youtube.com/vi/${isString ? video : video.id.videoId}/hqdefault.jpg`}
alt={
isString
? "YouTube video player"
: video.snippet.title
}
/>
)}
<button className="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%] text-white text-8xl cursor-pointer">
</button>
</>
)}
</div>
);
}