Compare commits
No commits in common. "2208b868c6fa797d7429f27496bb3e3d9f888d9f" and "0684a0649bb270eb1398853d27bf0e1caa869fe6" have entirely different histories.
2208b868c6
...
0684a0649b
11 changed files with 84 additions and 2556 deletions
|
|
@ -127,11 +127,3 @@ html,
|
||||||
body {
|
body {
|
||||||
@apply w-full h-full;
|
@apply w-full h-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-sonner-toast][data-styled='true'] [data-description] {
|
|
||||||
color: var(--primary) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-sonner-toaster][data-sonner-theme='dark'] [data-description] {
|
|
||||||
color: var(--primary) !important;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
import type { Colle } from "~/lib/api";
|
import type { Colle } from "~/lib/api";
|
||||||
|
|
||||||
import { Link } from "react-router";
|
import { Link, useNavigate } from "react-router";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
|
|
@ -26,14 +26,26 @@ const getSubjectEmoji = (_: string) => {
|
||||||
type ColleCardProps = {
|
type ColleCardProps = {
|
||||||
colle: Colle;
|
colle: Colle;
|
||||||
onToggleFavorite: (id: number, favorite: boolean) => void;
|
onToggleFavorite: (id: number, favorite: boolean) => void;
|
||||||
|
beforeClick: () => void;
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ColleCard({
|
export default function ColleCard({
|
||||||
colle,
|
colle,
|
||||||
onToggleFavorite,
|
onToggleFavorite,
|
||||||
|
beforeClick,
|
||||||
isFavorite,
|
isFavorite,
|
||||||
}: ColleCardProps) {
|
}: ColleCardProps) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// TODO: Remove this if scroll restoration is not needed (test first)
|
||||||
|
const handleCardClick = (e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
beforeClick();
|
||||||
|
setTimeout(() => navigate(`/colles/${colle.id}`), 100);
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: Favorites
|
// TODO: Favorites
|
||||||
const handleToggleFavorite = (e: React.MouseEvent) => {
|
const handleToggleFavorite = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation(); // Prevent card click
|
e.stopPropagation(); // Prevent card click
|
||||||
|
|
@ -46,7 +58,7 @@ export default function ColleCard({
|
||||||
const subjectEmoji = getSubjectEmoji(colle.subject.name);
|
const subjectEmoji = getSubjectEmoji(colle.subject.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/colles/${colle.id}`}>
|
<Link to={`/colles/${colle.id}`} onClick={handleCardClick}>
|
||||||
<Card
|
<Card
|
||||||
id={`colle-${colle.id}`}
|
id={`colle-${colle.id}`}
|
||||||
className="h-full cursor-pointer hover:shadow-md transition-shadow border-primary"
|
className="h-full cursor-pointer hover:shadow-md transition-shadow border-primary"
|
||||||
|
|
@ -82,7 +94,7 @@ export default function ColleCard({
|
||||||
)}
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="pb-0 pt-0 px-4">
|
<CardContent className="pb-0 pt-0 px-4" onClick={handleCardClick}>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,27 @@ export default function Home() {
|
||||||
// sessionStorage.setItem('student', studentFilter)
|
// sessionStorage.setItem('student', studentFilter)
|
||||||
}, [subjectFilter, examinerFilter]);
|
}, [subjectFilter, examinerFilter]);
|
||||||
|
|
||||||
|
// Restore scroll position
|
||||||
|
// TODO: Test and check if needed!!
|
||||||
|
// // SCROLL
|
||||||
|
// const setScrollPosition = (colleId: number) => {
|
||||||
|
// sessionStorage.setItem("colles_position", colleId.toString());
|
||||||
|
// };
|
||||||
|
// const restoreScrollPosition = () => {
|
||||||
|
// const position = sessionStorage.getItem("colles_position");
|
||||||
|
// if (position) {
|
||||||
|
// const element = document.getElementById(`colle-${position}`);
|
||||||
|
// if (element) {
|
||||||
|
// element.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
|
// sessionStorage.removeItem("colles_position");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// const location = useLocation();
|
||||||
|
// useEffect(() => {
|
||||||
|
// setTimeout(restoreScrollPosition, 500);
|
||||||
|
// }, [location]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6 pb-20 md:pb-0">
|
<div className="space-y-6 pb-20 md:pb-0">
|
||||||
{/* Week Navigation */}
|
{/* Week Navigation */}
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,11 @@ export default function TabContent({
|
||||||
<ColleCard
|
<ColleCard
|
||||||
key={colle.id}
|
key={colle.id}
|
||||||
colle={colle}
|
colle={colle}
|
||||||
|
beforeClick={() => {}}
|
||||||
onToggleFavorite={() => {}}
|
onToggleFavorite={() => {}}
|
||||||
isFavorite={false}
|
isFavorite={false}
|
||||||
|
// TODO: Implement scroll position handling
|
||||||
|
// beforeClick={() => setScrollPosition(colle.id)}
|
||||||
// TODO: Implement favorite toggle
|
// TODO: Implement favorite toggle
|
||||||
// onToggleFavorite={handleToggleFavorite}
|
// onToggleFavorite={handleToggleFavorite}
|
||||||
// isFavorite={isFavorite(colle)}
|
// isFavorite={isFavorite(colle)}
|
||||||
|
|
|
||||||
|
|
@ -84,16 +84,14 @@ export const useTheme = () => {
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isWindowAvailable = () => {
|
|
||||||
return typeof window !== "undefined" && window !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useDisplayedTheme = () => {
|
export const useDisplayedTheme = () => {
|
||||||
const { theme, setTheme } = useTheme();
|
const { theme, setTheme } = useTheme();
|
||||||
|
|
||||||
if (theme === "system") {
|
if (theme === "system") {
|
||||||
return {
|
return {
|
||||||
theme: isWindowAvailable() && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light",
|
theme: window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? "dark"
|
||||||
|
: "light",
|
||||||
setTheme,
|
setTheme,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
|
// TODO: Use theme hook
|
||||||
|
const { theme = "system" } = {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sonner
|
<Sonner
|
||||||
|
theme={theme as ToasterProps["theme"]}
|
||||||
className="toaster group"
|
className="toaster group"
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ import { Separator } from "~/components/ui/separator";
|
||||||
import UserDropdown from "~/components/user-dropdown";
|
import UserDropdown from "~/components/user-dropdown";
|
||||||
import ColleDetailsSkeleton from "~/components/details/skeleton-details";
|
import ColleDetailsSkeleton from "~/components/details/skeleton-details";
|
||||||
import AttachmentItem from "~/components/details/attachment";
|
import AttachmentItem from "~/components/details/attachment";
|
||||||
|
// TODO: Scroll restoration
|
||||||
|
// import { ScrollToTopOnMount } from "~/components/noscroll";
|
||||||
import Error from "~/components/error";
|
import Error from "~/components/error";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { AUTH_ERROR, useColle, useUser } from "~/lib/api";
|
import { AUTH_ERROR, useColle, useUser } from "~/lib/api";
|
||||||
|
|
@ -129,6 +131,8 @@ export default function ColleDetailPage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-6 px-4 pb-20 md:pb-6 md:py-8">
|
<div className="container mx-auto py-6 px-4 pb-20 md:pb-6 md:py-8">
|
||||||
|
{/* <ScrollToTopOnMount /> */}
|
||||||
|
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<Button variant="outline" onClick={() => goBack(navigate)}>
|
<Button variant="outline" onClick={() => goBack(navigate)}>
|
||||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,14 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-router/dev": "^7.5.3",
|
"@react-router/dev": "^7.5.3",
|
||||||
"@tailwindcss/vite": "^4.1.11",
|
"@tailwindcss/vite": "^4.1.4",
|
||||||
"@types/luxon": "^3.7.0",
|
"@types/luxon": "^3.7.0",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19.1.2",
|
"@types/react": "^19.1.2",
|
||||||
"@types/react-dom": "^19.1.2",
|
"@types/react-dom": "^19.1.2",
|
||||||
"tailwindcss": "^4.1.4",
|
"tailwindcss": "^4.1.4",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^7.0.6",
|
"vite": "^6.3.3",
|
||||||
"vite-plugin-pwa": "^1.0.2",
|
|
||||||
"vite-tsconfig-paths": "^5.1.4"
|
"vite-tsconfig-paths": "^5.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2529
pnpm-lock.yaml
generated
2529
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,35 +0,0 @@
|
||||||
export default {
|
|
||||||
workbox: {
|
|
||||||
importScripts: ["/sw/push.js"],
|
|
||||||
},
|
|
||||||
includeAssets: [
|
|
||||||
"favicon.ico",
|
|
||||||
"favicon-96x96.png",
|
|
||||||
"web-app-manifest-192x192.png",
|
|
||||||
"web-app-manifest-512x512.png",
|
|
||||||
"apple-touch-icon.png",
|
|
||||||
],
|
|
||||||
registerType: "autoUpdate",
|
|
||||||
manifest: {
|
|
||||||
lang: "fr",
|
|
||||||
name: "Khollisé ⚔️",
|
|
||||||
short_name: "Khollisé",
|
|
||||||
description: "BJColle but faster, better and prettier ⚡️",
|
|
||||||
theme_color: "#0d0d0d",
|
|
||||||
background_color: "#f4efe3",
|
|
||||||
orientation: "portrait",
|
|
||||||
display: "standalone",
|
|
||||||
icons: [
|
|
||||||
{
|
|
||||||
src: "/web-app-manifest-192x192.png",
|
|
||||||
sizes: "192x192",
|
|
||||||
type: "image/png",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: "/web-app-manifest-512x512.png",
|
|
||||||
sizes: "512x512",
|
|
||||||
type: "image/png",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
import { reactRouter } from "@react-router/dev/vite";
|
import { reactRouter } from "@react-router/dev/vite";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import pwaConfig from "./pwa.config";
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
import { VitePWA } from "vite-plugin-pwa";
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
// @ts-expect-error TODO: Fix type error with VitePWA
|
plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
|
||||||
plugins: [tailwindcss(), reactRouter(), tsconfigPaths(), VitePWA(pwaConfig)],
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue