Skip to content

Commit

Permalink
Merge branch 'feature/front-page'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gobot1234 committed Sep 19, 2024
2 parents e00fdc8 + acf5ccf commit 36e2476
Show file tree
Hide file tree
Showing 65 changed files with 2,237 additions and 799 deletions.
1 change: 1 addition & 0 deletions apps/anvil/dbschema/training.esdl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module training {
select .pages union .questions
order by .index
);
icon_url: str;

# things for the UI
multi locations: TrainingLocation;
Expand Down
1 change: 1 addition & 0 deletions apps/anvil/src/training/training.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export class TrainingService {
id: true,
description: true,
},
icon_url: true,
filter: e.all(
e.set(e.op(e.cast(TrainingLocation, location), "in", training.locations), e.op("exists", training.rep)),
),
Expand Down
3 changes: 2 additions & 1 deletion apps/forge/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
</script>

<!-- Meta Tags -->
<meta name="description" content="iForge - Empowering people through making and innovation at Sheffield University's premier makerspace."/>
<meta name="author" content="iForge Team"/>
<meta name="keywords" content="iForge, makerspace, innovation, making, collaboration, Sheffield University"/>
<meta name="description"
content="iForge - Empowering people to learn through making at Sheffield University's premier makerspace." />

<!-- Open Graph / Social Media Meta Tags -->
<meta property="og:title" content="iForge - Empowering People Through Making"/>
Expand Down
8 changes: 8 additions & 0 deletions apps/forge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
"@ignis/types": "workspace:*",
"@ignis/ui": "workspace:*",
"@nivo/calendar": "^0.85.1",
"@radix-ui/react-aspect-ratio": "^1.1.0",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-slot": "^1.0.2",
"@reduxjs/toolkit": "^2.2.5",
"@tailwindcss/typography": "^0.5.13",
"@tanstack/react-query": "^5.40.0",
Expand All @@ -35,11 +37,15 @@
"clsx": "^2.1.1",
"cmdk": "^0.2.1",
"date-fns": "^3.6.0",
"embla-carousel-autoplay": "^8.3.0",
"embla-carousel-react": "^8.3.0",
"embla-carousel-wheel-gestures": "^8.0.1",
"framer-motion": "^11.2.9",
"fuse.js": "^7.0.0",
"jotai": "^2.8.2",
"js-cookie": "^3.0.5",
"lucide-react": "^0.300.0",
"masonic": "^4.0.0",
"md5": "^2.3.0",
"memoize-one": "^6.0.0",
"next-themes": "^0.2.1",
Expand All @@ -56,11 +62,13 @@
"react-resizable-panels": "^1.0.10",
"react-responsive": "^9.0.2",
"react-spinners": "^0.13.8",
"react-wrap-balancer": "^1.1.1",
"redux-persist": "^6.0.0",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.0",
"sonner": "^1.4.41",
"tailwind-merge": "^2.3.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.3",
"tailwindcss-animate": "^1.0.7",
"uuid": "^9.0.1",
Expand Down
Binary file added apps/forge/public/1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/boba.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/hs front.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/hs inside.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/hs side.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/inspecting materials.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/ms front.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/ms inside.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/reps 2024.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/reps inspecting badges.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/users at the social space.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/using the dremel.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/using the electronics bench.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/using the laser cutter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/using the sewing machine.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/forge/public/using the water jet.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions apps/forge/src/components/auth-provider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react";
import { User } from "@ignis/types/users.ts";
import { useVerifyAuthentication } from "@/hooks/useVerifyAuthentication.ts";
import { Loader } from "@ui/components/ui/loader.tsx";
import { User } from "@ignis/types/users.ts";
import * as React from "react";
import { Loading } from "../routing/Loading";

export interface AuthContext {
isAuthenticated: boolean;
Expand All @@ -15,7 +15,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const { user, loading, setUser } = useVerifyAuthentication();

if (loading) {
return <Loader />;
return <Loading />;
}

const isAuthenticated = !!user;
Expand Down
29 changes: 29 additions & 0 deletions apps/forge/src/components/dot-indicator/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { cn } from "@/lib/utils";
import React from "react";

interface DotIndicatorProps {
count: number;
current: number;
orientation?: "horizontal" | "vertical";
className?: string;
}

const DotIndicator: React.FC<DotIndicatorProps> = ({ count, current, orientation = "horizontal", className }) => {
return (
<div
className={cn(
`absolute flex transform ${orientation === "horizontal" ? "bottom-0 left-1/2 -translate-x-1/2 space-x-2" : "right-0 top-1/2 -translate-y-1/2 flex-col space-y-2"}`,
className,
)}
>
{[...Array(count)].map((_, index) => (
<div
key={index}
className={`w-4 h-4 rounded-lg transition-colors duration-300 border-2 ${current === index + 1 ? "border-accent-foreground" : "border-accent"}`}
/>
))}
</div>
);
};

export default DotIndicator;
139 changes: 139 additions & 0 deletions apps/forge/src/components/footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { Link } from "@tanstack/react-router";
import { Separator } from "@ui/components/ui/separator";
import Balancer from "react-wrap-balancer";
import { LocationIcon } from "../icons/Locations";

import { Entries, removeSuffix, toTitleCase } from "@/lib/utils";
import { locationStatus } from "@/services/signin/locationService";
import { PartialLocation } from "@ignis/types/sign_in";
import { useQuery } from "@tanstack/react-query";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@ui/components/ui/tooltip";
import { DiscordIcon, GitHubIcon, InstagramIcon, LinkedInIcon, TwitterIcon, YouTubeIcon } from "../icons/Socials";
import { IForgeLogo } from "../icons/iforge";

function LocationStatusTooltip({ location }: { location: PartialLocation }) {
let className: string;
let tooltip: string;

switch (location.status) {
case "closed":
className = "bg-cross";
tooltip = "Closed";
break;
case "open":
className = "bg-tick";
tooltip = "Open";
break;
case "soon":
className = "bg-orange-500";
tooltip = "Opening/Closing Soon";
break;
default:
throw new Error("Unreachable"); // TODO make this grey if the backend is down
}
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div className="p-2 ml-0.5 hover:cursor-pointer">
<div className={`size-2 ${className} rounded-lg`} />
</div>
</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}

export default function Footer() {
const { data: locationStatuses } = useQuery({
queryKey: ["locationStatus"],
queryFn: locationStatus,
staleTime: 20_000,
});

return (
<footer>
<br />
<br />
<div className="bg-card border-t-2 p-10">
<div className="flex justify-between items-end mx-5">
<div className="flex flex-col gap-2 not-prose max-w-[30rem]">
<Link to="/">
<h3 className="sr-only">iForge Makerspace</h3>
<IForgeLogo className="w-[250px] hover:opacity-75 transition-all" />
</Link>

<p className="mt-3">
<Balancer>
iForge Makerspace at the University of Sheffield is the place to design and create, offering tools and
resources for students and staff to bring their ideas to life
</Balancer>
</p>
</div>
<div className="flex flex-col gap-2">
<h5 className="text-lg font-bold">Opening Hours</h5>
<Balancer ratio="0.5">Open weekdays, subject to exams and holidays</Balancer>
{locationStatuses && (
<table className="w-full border-collapse items-center flex">
<tbody>
{(Object.entries(locationStatuses) as Entries<typeof locationStatuses>).map(([name, location]) => (
<tr key={name} className="py-2">
<td>
<div className="flex items-center justify-center h-full">
<LocationIcon location={name} className="h-4" tooltip={false} />
</div>
</td>
<td className="pr-2">
<div className="flex items-center h-full">{toTitleCase(name)}</div>
</td>
<td>
<div className="flex items-center justify-between h-full">
<span>
{removeSuffix(location.opening_time, ":00")} to {removeSuffix(location.closing_time, ":00")}
</span>
<LocationStatusTooltip location={location} />
</div>
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
<div className="flex flex-col gap-2">
<h5 className="text-lg font-bold">Website</h5>
<Link to="/locations" className="hover:underline underline-offset-4">
Locations
</Link>
<Link to="/projects" className="hover:underline underline-offset-4">
Projects
</Link>
<Link to="/about" className="hover:underline underline-offset-4">
About Us
</Link>
<Link to="/contact" className="hover:underline underline-offset-4">
Contact
</Link>
</div>
</div>
<br />
<Separator />
<br />
<div className="not-prose flex flex-col md:flex-row md:gap-2 gap-6 justify-between md:items-center mx-5">
<div className="flex gap-2">
<GitHubIcon />
<DiscordIcon />
<InstagramIcon />
<LinkedInIcon />
<TwitterIcon />
<YouTubeIcon />
</div>
<p className="text-muted-foreground">© iForge Makerspace. All rights reserved. 2017-present.</p>
</div>
</div>
</footer>
);
}
29 changes: 29 additions & 0 deletions apps/forge/src/components/icons/Socials.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Button } from "@ui/components/ui/button";

const SocialIcon = ({ icon, altText, href }: { icon: string; altText: string; href: string }) => {
return (
<a href={href}>
<Button variant="outline" size="icon">
<img src={`${import.meta.env.VITE_CDN_URL}/icons/${icon}.svg`} className="dark:invert h-6" alt={altText} />
</Button>
</a>
);
};

export const GitHubIcon = () => <SocialIcon icon="github" altText="GitHub" href="https://github.com/iforge-uos" />;

export const DiscordIcon = () => <SocialIcon icon="discord" altText="Discord" href="https://discord.gg/UK6e8GeArH" />;

export const InstagramIcon = () => (
<SocialIcon icon="instagram" altText="Instagram" href="https://instagram.com/iforge_uos" />
);

export const LinkedInIcon = () => (
<SocialIcon icon="linkedin" altText="LinkedIn" href="https://www.linkedin.com/company/iforge" />
);

export const TwitterIcon = () => <SocialIcon icon="twitter" altText="Twitter" href="https://twitter.com/iForgeUoS" />;

export const YouTubeIcon = () => (
<SocialIcon icon="youtube" altText="YouTube" href="https://www.youtube.com/@iforge_uos" />
);
13 changes: 13 additions & 0 deletions apps/forge/src/components/icons/iforge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useTheme } from "@/providers/themeProvider/use-theme";

// n.b does not work if leading char is lowercase because lol
export const IForgeLogo = ({ className }: { className?: string }) => {
const { normalisedTheme } = useTheme();
return (
<img
src={`${import.meta.env.VITE_CDN_URL}/logos/iforge${normalisedTheme === "dark" ? "-dark" : ""}.png`} // TODO switch to svg
alt="Logo"
className={className}
/>
);
};
39 changes: 39 additions & 0 deletions apps/forge/src/components/loading/img.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { cn } from "@/lib/utils";
import { Skeleton } from "@ui/components/ui/skeleton";
import React, { useState } from "react";

interface ImageWithPlaceholderProps {
src: string;
alt: string;
className?: string;
aspectRatio?: string;
}

const ImageWithPlaceholder: React.FC<ImageWithPlaceholderProps> = ({
src,
alt,
className,
aspectRatio = "360/240",
}) => {
const [imageLoaded, setImageLoaded] = useState(false);

const aspectRatioStyle =
aspectRatio
.split("/")
.map(Number)
.reduce((p, c) => c / p) * 100;

return (
<div className="relative" style={{ paddingBottom: `${aspectRatioStyle}%` }}>
<img
src={src}
alt={alt}
onLoad={() => setImageLoaded(true)}
className={cn("absolute w-full h-full object-cover", className, { hidden: !imageLoaded })}
/>
{!imageLoaded && <Skeleton className="absolute top-0 left-0 w-full h-full" />}
</div>
);
};

export default ImageWithPlaceholder;
4 changes: 2 additions & 2 deletions apps/forge/src/components/navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import AppNav from "@/components/navbar/appNav";
import AppSwitcher from "@/components/navbar/appSwitcher";
import { ThemeSwitcher } from "@/components/navbar/themeSwitcher";
import { UserNav } from "@/components/navbar/userNav";
import AppNav from "@/components/navbar/appNav";

export default function NavBar() {
return (
<div className="flex items-center justify-between h-[60px] p-3 w-full bg-card text-card-foreground backdrop-filter shadow-lg dark:shadow-none">
<div className="sticky top-0 z-40 flex items-center justify-between h-[60px] p-3 w-full bg-card text-card-foreground backdrop-filter shadow-lg dark:shadow-none border-b-2">
<div className="flex flex-1">
<AppSwitcher />
</div>
Expand Down
27 changes: 27 additions & 0 deletions apps/forge/src/components/training/ImageGradient.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { useMediaQuery } from "react-responsive";

interface ImageGradientProps {
gradientColor: string;
gradientAmount?: number; // must be in [0, 1]
children: React.ReactNode;
}

const ImageGradient: React.FC<ImageGradientProps> = ({ gradientColor, gradientAmount = 0.5, children }) => {
const isMediumScreen = useMediaQuery({ minWidth: 768 });
const gradientPercentage = `${gradientAmount * 100 * (isMediumScreen ? 1 : 1.25)}%`;

return (
<div className="overflow-hidden rounded-lg">
{children}
<div
className="absolute inset-0"
style={{
background: `linear-gradient(to top, var(--${gradientColor}) 5%, transparent ${gradientPercentage})`,
}}
/>
</div>
);
};

export default ImageGradient;
Loading

0 comments on commit 36e2476

Please sign in to comment.