Merge branch 'main' into andy/reduce-flicker

This commit is contained in:
Andy Smithwick 2025-01-31 18:14:01 -08:00
commit fbc7feba56
195 changed files with 3419 additions and 893 deletions

1483
bun.lock Normal file

File diff suppressed because it is too large Load diff

BIN
bun.lockb

Binary file not shown.

4
nixpacks.toml Normal file
View file

@ -0,0 +1,4 @@
[phases.setup]
nixPkgs = ["nodejs_18", "bun"]
aptPkgs = ["curl", "wget"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

BIN
public/404.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

BIN
public/calendar.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

BIN
public/halloween.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

BIN
public/hardhack.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

BIN
public/map.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/officers/akhil.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,020 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/officers/allie.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 KiB

BIN
public/officers/andy.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/officers/anika.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

BIN
public/officers/anu.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/officers/ashlee.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

BIN
public/officers/dhruv.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/officers/dihan.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

BIN
public/officers/emma.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/officers/erik.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/officers/lauren.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

BIN
public/officers/lisa.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

BIN
public/officers/philip.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

BIN
public/officers/pranav.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

BIN
public/officers/ridhi.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

BIN
public/officers/rohil.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/officers/shing.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/officers/shipra.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 KiB

BIN
public/officers/stella.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

BIN
public/officers/steph.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

BIN
public/officers/terri.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

BIN
public/officers/zarif.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

BIN
public/project.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

BIN
public/robocup.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

BIN
public/signal.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

BIN
public/supercomp.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -1,3 +1,166 @@
---
const { filters, currentFilter } = Astro.props;
---
---
<div class="inline-flex border border-white/20 rounded-full md:p-[0.2vw] p-[0.4vw] relative my-[3vw]">
<div
id="slider"
class="absolute h-[calc(100%-15%)] bg-[#FFB81C] rounded-full transition-none"
style="left: 1%;"
>
</div>
{
filters.map((filter) => (
<button
data-filter={filter}
class={`md:text-[1.3vw] text-[2.5vw] md:px-[1.8vw] px-[3vw] md:py-[0.2vw] py-[0.4vw] rounded-full transition-all relative z-10 ${
currentFilter === filter
? "text-black"
: "text-white hover:bg-white/10 hover:bg-opacity-50"
}`}
>
{filter}
</button>
))
}
</div>
<script>
const buttons = document.querySelectorAll("[data-filter]");
const officers = document.querySelectorAll("[data-officer]");
const container = officers[0]?.parentElement;
const slider = document.getElementById("slider");
// Define type order for consistent sorting
const typeOrder = ["Executives", "Internal", "Events", "Projects"];
function getTypeWeight(type) {
const index = typeOrder.indexOf(type);
return index === -1 ? typeOrder.length : index;
}
function sortOfficersByType() {
const officerArray = Array.from(officers);
officerArray.sort((a, b) => {
const aTypes = JSON.parse(a.getAttribute("data-types"));
const bTypes = JSON.parse(b.getAttribute("data-types"));
return getTypeWeight(aTypes[0]) - getTypeWeight(bTypes[0]);
});
officerArray.forEach((officer) => {
container.appendChild(officer);
});
}
function moveSlider(button) {
if (!slider) return;
const buttonRect = button.getBoundingClientRect();
const containerRect = button.parentElement.getBoundingClientRect();
slider.style.width = `${buttonRect.width}px`;
slider.style.left = `${buttonRect.left - containerRect.left}px`;
}
function updateFilter(selectedFilter, clickedButton) {
// Update button styles
buttons.forEach((btn) => {
const isSelected =
btn.getAttribute("data-filter") === selectedFilter;
btn.classList.toggle("text-black", isSelected);
btn.classList.toggle("text-white", !isSelected);
btn.classList.toggle("hover:bg-white/10", !isSelected);
btn.classList.toggle("hover:bg-opacity-50", !isSelected);
});
// move slider
moveSlider(clickedButton);
// fades out all officers
officers.forEach((officer) => {
officer.style.opacity = "0";
officer.style.transition = "opacity 300ms ease-out";
});
// waits, then removes and re-adds officers
setTimeout(() => {
// removes all officers from container
officers.forEach((officer) => {
officer.remove();
});
// filters officers and prepares them for re-insertion
const officersToShow = Array.from(officers).filter((officer) => {
const types = JSON.parse(
officer.getAttribute("data-types") || "[]"
);
return (
selectedFilter === "All" || types.includes(selectedFilter)
);
});
// sorts if needed
if (selectedFilter === "All") {
officersToShow.sort((a, b) => {
const aTypes = JSON.parse(a.getAttribute("data-types"));
const bTypes = JSON.parse(b.getAttribute("data-types"));
return getTypeWeight(aTypes[0]) - getTypeWeight(bTypes[0]);
});
}
// sets initial opacity to 0 for fade in
officersToShow.forEach((officer) => {
officer.style.opacity = "0";
officer.style.display = "";
container.appendChild(officer);
});
// triggers reflow and fades in
requestAnimationFrame(() => {
officersToShow.forEach((officer) => {
officer.style.opacity = "1";
});
});
}, 300); // matches fade-out duration
}
sortOfficersByType();
// init
const initialButton = Array.from(buttons).find(
(btn) => btn.getAttribute("data-filter") === "All"
);
// init
if (initialButton && slider) {
const buttonRect = initialButton.getBoundingClientRect();
slider.style.width = `${buttonRect.width}px`;
// turns on transitions
requestAnimationFrame(() => {
slider.classList.remove("transition-none");
slider.classList.add(
"transition-all",
"duration-300",
"ease-in-out"
);
});
}
// reveals officers after sorting with animation
requestAnimationFrame(() => {
officers.forEach((officer) => {
officer.style.transition = "opacity 300ms ease-out";
officer.style.visibility = "visible";
// triggers reflow
officer.offsetHeight;
officer.style.opacity = "1";
});
});
// addss click handlers
buttons.forEach((button) => {
button.addEventListener("click", () => {
const filterValue = button.getAttribute("data-filter");
updateFilter(filterValue, button);
});
});
</script>

View file

@ -2,32 +2,55 @@
import { FaGear } from "react-icons/fa6";
import { MdEmail } from "react-icons/md";
import Link from "next/link";
import { Image } from "astro:assets";
const { name, position, picture, email } = Astro.props;
---
<div class = "text-white">
<div class="text-white">
<div class="text-ieee-yellow">
<Link href="s1hung@ucsd.edu" className = "flex items-center ml-[3%] py-[0.5vh]">
<MdEmail className = "text-[1.5vw] mr-[0.5%]"/>
<p class = "text-[0.8vw]">
<Link
href={`mailto:${email}`}
className="flex items-center ml-[3%] py-[0.5vh] group"
>
<MdEmail
className="md:text-[1.5vw] text-[2.5vw] mr-[0.5%] group-hover:scale-110 group-hover:opacity-70 duration-300"
/>
<p class="md:text-[0.8vw] text-[2vw]">
{email}
</p>
</Link>
</div>
<div class = "w-[20vw] aspect-[334/440] bg-gradient-to-t from-ieee-blue-100/5 to-ieee-blue-100/25 rounded-[10%] flex flex-col items-center">
<img src ={picture} alt = "officer" class = "w-[18vw] rounded-[10%] pt-[5%] pb-[3%] relative" >
<div class = "bg-white w-fit rounded-full aspect-square p-[0.4vw] text-ieee-black text-[1.8vw] absolute ml-[13.5vw] mt-[3vh]">
<div
class="md:w-[20vw] w-[35vw] aspect-[334/440] bg-gradient-to-t from-ieee-blue-100/5 to-ieee-blue-100/25 rounded-[10%] flex flex-col items-center relative"
>
<Image
src={picture}
alt="officer"
class="md:w-[18vw] w-[31vw] md:rounded-[1.5vw] rounded-[3vw] mt-[5%] mb-[3%]"
width={334}
height={440}
/>
<div
class="bg-white w-fit rounded-full aspect-square md:p-[0.4vw] p-[0.8vw] text-ieee-black md:text-[1.8vw] text-[3.5vw] absolute md:right-[1.5vw] md:top-[1.5vw] right-[2.5vw] top-[2.5vw]"
>
<FaGear />
</div>
<div class = "w-full flex justify-between px-[7%]">
<p data-inview class = "opacity-0 in-view:animate-fade-right text-[2vw] font-light leading-[4.5vh]">
<div
class="flex w-[85%] justify-between"
>
<p
data-inview
class="in-view:animate-fade-right md:text-[2vw] text-[3.5vw] font-light md:leading-[2.5vw] leading-[5vw] w-[10vw]"
>
{name}
</p>
<div data-inview class = "opacity-0 in-view:animate-fade-up text-[0.8vw] w-[8vw] border-[0.11vw] border-white/90 rounded-full p-[0.5%] h-fit text-center">
<div
data-inview
class="md:mt-[0.5vw] mt-[1.5vw] in-view:animate-fade-up md:text-[0.8vw] text-[1.5vw] w-fit border-[0.11vw] border-white/90 rounded-full px-[1vw] py-[0.1vw] h-fit text-center"
>
{position}
</div>
</div>
</div>
</div>

View file

@ -1,42 +1,63 @@
---
import about from "../../images/about.png";
import about from "../../images/about.webp";
import { Image } from "astro:assets";
import neko from "../../images/neko.png";
import neko from "../../images/neko.webp";
import { LiaDotCircle } from "react-icons/lia";
import Officer from "../board/Officer.astro";
import Filter from "../board/Filter.astro";
import officers from "../../data/officers.json";
// Get all unique types and add 'All' option
const typeOrder = ["Executives", "Internal", "Events", "Projects"];
const types = ["All", ...typeOrder];
const currentFilter = "All";
---
<div class="text-white flex flex-col items-center mt-[15vh] mb-[10vh]">
<div data-inview class="relative w-[21vw] in-view:animate-fade-down">
<div
class="text-white flex flex-col items-center md:mt-[5vw] mt-[10vw] mb-[10vh]"
>
<div
data-inview
class="relative w-[40vw] md:w-[21vw] mb-[10vh] in-view:animate-fade-down"
>
<Image src={about} alt="About background image" />
<Image
src={neko}
alt="About image"
class="absolute top-[10%] left-[16%] aspect-[399/491] object-cover w-[14vw] rounded-[2vw]"
class="absolute top-[10%] left-[16%] aspect-[399/491] object-cover w-[27vw] md:w-[14vw] rounded-[2vw]"
/>
</div>
<div class="text-[2.5vw] flex items-center mt-[2vh]">
<div class="text-[5vw] md:text-[2.5vw] flex items-center mt-[1vw]">
<LiaDotCircle className="mr-[1vw] pt-[0.5%]" />
<p>MEET THE BOARD</p>
</div>
<p class="text-[1.3vw] w-[56%] my-[3%] font-extralight text-center">
Erat hendrerit tristique erat; parturient cursus fringilla feugiat. Eget
faucibus fames ridiculus nec egestas convallis cubilia malesuada. Tellus
nibh vivamus tempus molestie tristique quis
<p
class="md:text-[1.3vw] text-[2.5vw] md:w-[56%] w-[70%] my-[3%] font-extralight text-center"
>
Our board comprises 31 students of varying majors, colleges, and interests!
Feel free to reach out for any questions about our position or experiences.
</p>
<div class="grid gap-[3vw] grid-cols-3 mt-[10vh]">
<Filter filters={types} currentFilter={currentFilter} />
<div class="grid gap-[3vw] md:grid-cols-3 grid-cols-2 mt-[2vh]">
{
officers.map((officer) => (
<div
data-officer
data-types={JSON.stringify(officer.type)}
style="opacity: 0; visibility: hidden"
>
<Officer
name={officer.name}
position={officer.position}
picture={officer.picture}
email={officer.email}
/>
</div>
))
}
</div>

View file

@ -4,14 +4,14 @@ const {title, text} = Astro.props;
---
<div class="flex flex-col items-center text-white my-[10%]">
<div class="flex items-center text-[2.5vw] mb-[3%]">
<div class="flex items-center text-[4.5vw] md:text-[2.5vw] mb-[3%]">
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]"/>
<p class="text-transparent bg-clip-text bg-gradient-to-b from-white via-white to-ieee-black">
{title}
</p>
</div>
<p class="w-[70%] text-[1.4vw] font-light ">
<p class="w-[70%] md:text-[1.4vw] text-[2vw] font-light ">
{text}
</p>
</div>

View file

@ -5,22 +5,22 @@ import whiteLogoHorizontal from "../../images/logos/white_logo_horizontal.svg";
import { IoHeart } from "react-icons/io5";
---
<div class="w-full py-[2%] flex justify-center">
<div class="w-full md:py-[2%] py-[3vw] flex justify-center">
<div
class="w-[95%] bg-black/40 py-[1%] px-[1.5%] rounded-[2vw] border-[0.1vw] flex justify-between"
class="w-[95%] bg-black/40 md:py-[1%] py-[2vw] px-[1.5%] rounded-[2vw] border-[0.1vw] flex justify-between"
>
<Link href="/" className="hover:opacity-70 duration-300">
<Image
class="w-[15vw]"
class="md:w-[15vw] w-[35vw]"
src={whiteLogoHorizontal}
alt="IEEE UCSD Logo"
/>
</Link>
<div class="flex items-center">
<p class="text-white text-[1.2vw]">
<p class="text-white md:text-[1.2vw] text-[2.7vw]">
made by IEEE UCSD webmasters with
</p>
<IoHeart className=" text-ieee-blue-100 ml-[1vw] text-[1.5vw]" />
<IoHeart className=" text-ieee-blue-100 ml-[1vw] md:text-[1.5vw] text-[4vw]" />
</div>
</div>
</div>

View file

@ -4,13 +4,18 @@ import whiteLogoHorizontal from "../../images/logos/white_logo_horizontal.svg";
import pages from "../../data/pages.json";
---
<div class="md:w-full w-fit fixed z-10">
<div class="w-full">
<div
class="flex justify-between items-center bg-black my-[1%] mx-[2.5%] py-[0.5%] px-[1%] md:rounded-full md:border-[0.1vw]"
class="flex justify-between items-center bg-ieee-black my-[1%] mx-[2.5%] py-[0.5%] px-[1%] rounded-full md:border-[0.1vw]"
>
<a href="/" class="hover:opacity-60 duration-300 hidden md:flex">
<a href="/" class="hover:opacity-60 duration-300">
<Image
class="w-[15vw]"
class="w-[15vw] md:block hidden"
src={whiteLogoHorizontal}
alt="IEEE UCSD Logo"
/>
<Image
class="w-[40vw] md:hidden block"
src={whiteLogoHorizontal}
alt="IEEE UCSD Logo"
/>
@ -76,17 +81,17 @@ import pages from "../../data/pages.json";
class="fixed inset-0 z-[51] hidden xl:hidden motion-safe:transition-transform motion-safe:duration-300 translate-x-full"
>
<div
class="flex flex-col items-center h-[70vh] justify-evenly bg-black"
class="flex flex-col items-center min-h-screen justify-center bg-black py-20 px-4 space-y-8"
>
{
pages.map((page) => (
<a
href={page.path}
class={`block py-2 px-8 text-center rounded-[3rem] motion-safe:transition-colors motion-safe:duration-200 uppercase font-bold text-xl
class={`block py-4 px-12 text-center rounded-[3rem] motion-safe:transition-colors motion-safe:duration-200 uppercase font-bold text-2xl w-full max-w-md
${
page.name === "Online Store"
? "bg-[#f3c135] text-black border-[#f3c135] hover:bg-[#dba923] hover:border-[#dba923]"
: "text-white hover:text-gray-300 border-white"
: "text-white hover:text-gray-300 border-white border-2"
}`}
>
{page.name}

View file

@ -1,11 +1,11 @@
---
const {question, answer} = Astro.props;
---
<div class = "text-white w-full flex flex-col mb-[2vh]">
<p data-inview class = "in-view:animate-fade-right text-ieee-yellow text-[1.4vw] mb-[2vh] font-semibold pl-[1vw]">
<div class = "text-white w-full flex flex-col mb-[2vh] animate-ease-in-out">
<p data-inview class = "in-view:animate-fade-right text-ieee-yellow text-[2.5vw] md:text-[1.4vw] mb-[2vh] font-semibold pl-[1vw]">
{question}
</p>
<p data-inview class = "w-[60%] mb-[2vh] pl-[1vw] in-view:animate-fade-left">
<p data-inview class = "md:w-[70%] w-[80%] mb-[2vh] pl-[1vw] text-[2vw] md:text-[1.2vw] in-view:animate-fade-left animate-ease-in-out">
{answer}
</p>
<dev>

View file

@ -4,8 +4,8 @@ import { LiaDotCircle } from "react-icons/lia";
const {faq} = Astro.props;
---
<div class = "text-white w-full h-[90vh] ml-[15vw] mb-[20%] mt-[10%]">
<div class = "text-[2.5vw] flex items-center my-[7vh]">
<div class = "text-white md:ml-[15vw] ml-[10vw] mb-[20%] mt-[10%]">
<div class = "text-[4.5vw] md:text-[2.5vw] flex items-center my-[7vh]">
<LiaDotCircle className = "mr-[1vw]" />
<p>
Frequently Asked Questions

View file

@ -1,71 +1,79 @@
---
import { LiaDotCircle } from "react-icons/lia";
import { Image } from "astro:assets";
import evan from "../../images/evan.png";
import { FaDiscord, FaFacebook } from "react-icons/fa";
import jellyfish from "../../images/jellyfish.webp";
import { FaDiscord } from "react-icons/fa";
import { RiInstagramFill } from "react-icons/ri";
import { MdEmail } from "react-icons/md";
import Link from "next/link";
---
<div class="text-white flex flex-col items-center h-[65vh] justify-between">
<div class="flex items-center text-[2.5vw]">
<div
class="text-white flex flex-col items-center md:h-[35vw] h-[60vw] justify-between"
>
<div class="flex items-center text-[4.5vw] md:text-[2.5vw]">
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]" />
<p>Social Media</p>
</div>
<p class="w-1/3 text-center text-[1.2vw] pb-[5%]">
Lorem ipsum is placeholder text commonly used in the graphic, print, and
publishing industries f
<p class="md:w-1/3 w-3/5 text-center text-[2vw] md:text-[1.2vw] pb-[5%]">
Stay connected with us on Discord, Facebook, and Instagram! We regularly
post information on upcoming events and competitions.
</p>
<div
class="w-[85%] rounded-[3vw] bg-gradient-to-r from-ieee-blue-300 to-ieee-blue-100 relative h-[30vh] flex items-center text-white/90"
>
<div data-inview class="w-2/5 flex justify-evenly ml-[5%] in-view:animate-flip-up animate-duration-1000">
<Link
href="https://discord.gg/XxfjqZSjca"
target="_blank"
className="flex flex-col items-center"
class="md:w-[85%] w-full rounded-[3vw] bg-gradient-to-r from-ieee-blue-300 to-ieee-blue-100 relative md:h-[15vw] h-[30vw] flex items-center text-white/90"
>
<div
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
data-inview
class="md:w-2/5 w-1/2 flex justify-evenly ml-[5%] animate-ease-in-out in-view:animate-flip-up animate-duration-1000"
>
<FaDiscord />
</div>
<p class="text-[1.3vw] font-semibold">Discord</p>
</Link>
<Link
href="https://www.facebook.com/ieeeucsd"
target="_blank"
className="flex flex-col items-center"
>
<div
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
>
<FaFacebook />
</div>
<p class="text-[1.3vw] font-semibold">Facebook</p>
</Link>
<Link
href="https://www.instagram.com/ieee.ucsd"
target="_blank"
className="flex flex-col items-center"
>
<div
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[5vw] md:text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
>
<RiInstagramFill />
</div>
<p class="text-[1.3vw] font-semibold">Instagram</p>
<p class="text-[2vw] md:text-[1.3vw] font-semibold">
Instagram
</p>
</Link>
<Link
href="https://discord.gg/XxfjqZSjca"
target="_blank"
className="flex flex-col items-center"
>
<div
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[5vw] md:text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
>
<FaDiscord />
</div>
<p class="text-[2vw] md:text-[1.3vw] font-semibold">Discord</p>
</Link>
<Link
href="mailto:ieee@ucsd.edu"
target="_blank"
className="flex flex-col items-center"
>
<div
class="border-[0.15vw] rounded-full shadow-glow hover:scale-110 duration-300 p-[1vw] text-[5vw] md:text-[2.2vw] text-ieee-black/80 border-ieee-blue-100 bg-gradient-radial from-white to-ieee-blue-100"
>
<MdEmail />
</div>
<p class="text-[2vw] md:text-[1.3vw] font-semibold">Email</p>
</Link>
</div>
<Image
data-inview
src={evan}
src={jellyfish}
alt="cat placeholder"
class="absolute -bottom-[10vh] w-[25vw] right-0 in-view:animate-wiggle"
class="absolute bottom-0 md:w-[25vw] w-[35vw] right-[4vw] animate-wiggle animate-infinite"
/>
</div>
</div>

View file

@ -3,7 +3,7 @@ const {title} = Astro.props;
import { LiaDotCircle } from "react-icons/lia";
---
<div class="flex items-center text-[2.5vw] mb-[5%]">
<div class="flex items-center md:text-[2.5vw] text-[4vw] mb-[5%]">
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]"/>
<p>
{title}

View file

@ -3,7 +3,9 @@ const {title} = Astro.props;
import { LiaDotCircle } from "react-icons/lia";
---
<div class="flex items-center text-[3vw] ml-[10%] pt-[10%] text-white font-semibold">
<div
class="flex items-center md:text-[3vw] text-[4.5vw] ml-[10%] md:pt-[5%] pt-[10%] text-white font-semibold"
>
<LiaDotCircle className=" mr-[1vw] text-[2.7vw]" />
<p>
{title}

View file

@ -0,0 +1,358 @@
import React, { useState, useEffect } from "react";
const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
const [currentDate, setCurrentDate] = useState(new Date());
const [events, setEvents] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [hoveredEvent, setHoveredEvent] = useState(null);
const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
const getDaysInMonth = (date) => {
const year = date.getFullYear();
const month = date.getMonth();
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const daysInMonth = lastDay.getDate();
const startingDay = firstDay.getDay();
const endingDay = lastDay.getDay();
const days = [];
// Add empty slots for days before the first of the month
for (let i = 0; i < startingDay; i++) {
days.push(null);
}
// Add all days of the month
for (let i = 1; i <= daysInMonth; i++) {
days.push(new Date(year, month, i));
}
// Add empty slots for remaining days in the last week
const remainingDays = 6 - endingDay;
for (let i = 0; i < remainingDays; i++) {
days.push(null);
}
return days;
};
// Format date to match event dates
const formatDate = (date) => {
if (!date) return "";
return date.toISOString().split("T")[0];
};
// Get events for a specific day
const getEventsForDay = (day) => {
if (!day) return [];
const dayStr = formatDate(day);
return events.filter((event) => {
const eventDate = event.start.dateTime
? new Date(event.start.dateTime).toISOString().split("T")[0]
: event.start.date;
return eventDate === dayStr;
});
};
// Format time for display
const formatEventTime = (dateTimeStr) => {
if (!dateTimeStr) return "";
const date = new Date(dateTimeStr);
return date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});
};
useEffect(() => {
const calendarId = EVENT_CALENDAR_ID;
const userTimeZone = "America/Los_Angeles";
const loadGapiAndListEvents = async () => {
try {
console.log("Starting to load events...");
if (typeof window.gapi === "undefined") {
console.log("Loading GAPI script...");
await new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/api.js";
document.body.appendChild(script);
script.onload = () => {
console.log("GAPI script loaded");
window.gapi.load("client", resolve);
};
script.onerror = () => {
console.error("Failed to load GAPI script");
reject(new Error("Failed to load the Google API script."));
};
});
}
console.log("Initializing GAPI client...");
await window.gapi.client.init({
apiKey: CALENDAR_API_KEY,
discoveryDocs: [
"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
],
});
// Get first and last day of current month
const firstDay = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
1,
);
const lastDay = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0,
);
console.log("Fetching events...");
const response = await window.gapi.client.calendar.events.list({
calendarId: calendarId,
timeZone: userTimeZone,
singleEvents: true,
timeMin: firstDay.toISOString(),
timeMax: lastDay.toISOString(),
orderBy: "startTime",
});
console.log("Response received:", response);
if (response.result.items) {
setEvents(response.result.items);
}
} catch (error) {
console.error("Detailed Error: ", error);
setError(error.message || "Failed to load events");
} finally {
setLoading(false);
}
};
if (!CALENDAR_API_KEY) {
setError("API key is missing");
setLoading(false);
return;
}
setLoading(true);
loadGapiAndListEvents();
}, [CALENDAR_API_KEY, currentDate]);
const monthNames = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const changeMonth = (increment) => {
setCurrentDate(
new Date(
currentDate.getFullYear(),
currentDate.getMonth() + increment,
1,
),
);
};
const handleEventMouseEnter = (event, e) => {
const target = e.target;
setTooltipPosition({
x: e.clientX,
y: e.clientY,
});
setHoveredEvent({ event, target });
};
const handleEventMouseLeave = () => {
setHoveredEvent(null);
};
const handleMouseMove = (e) => {
if (hoveredEvent) {
// Check if the mouse is still over the event element
const rect = hoveredEvent.target.getBoundingClientRect();
const isStillHovering =
e.clientX >= rect.left &&
e.clientX <= rect.right &&
e.clientY >= rect.top &&
e.clientY <= rect.bottom;
if (!isStillHovering) {
setHoveredEvent(null);
} else {
setTooltipPosition({
x: e.clientX,
y: e.clientY,
});
}
}
};
useEffect(() => {
const handleScroll = () => {
if (hoveredEvent) {
const rect = hoveredEvent.target.getBoundingClientRect();
const mouseX = tooltipPosition.x - 15; // Subtract the offset added to the tooltip
const mouseY = tooltipPosition.y - 15;
const isStillHovering =
mouseX >= rect.left &&
mouseX <= rect.right &&
mouseY >= rect.top &&
mouseY <= rect.bottom;
if (!isStillHovering) {
setHoveredEvent(null);
}
}
};
window.addEventListener("scroll", handleScroll, true);
return () => window.removeEventListener("scroll", handleScroll, true);
}, [hoveredEvent, tooltipPosition]);
if (!CALENDAR_API_KEY) {
return (
<div className="text-white">
Error: Calendar API key is not configured
</div>
);
}
return (
<div
className="md:w-[90vw] w-[95vw] mx-auto p-[3vw] relative z-10"
onMouseMove={handleMouseMove}
>
{/* Hovering Calendar Header */}
<div className="flex justify-center mb-[2vw]">
<div className="bg-gradient-to-t from-ieee-blue-100/5 to-ieee-blue-100/25 rounded-[1.5vw] p-[1vw] backdrop-blur-sm w-[30vw] px-[2vw]">
<div className="flex items-center gap-[3vw]">
<button
onClick={() => changeMonth(-1)}
className="text-white hover:text-ieee-yellow transition-colors text-[2vw] bg-ieee-black/40 w-[4vw] h-[4vw] rounded-[1vw] flex items-center justify-center"
>
</button>
<h2 className="text-white text-[2.5vw] font-bold whitespace-nowrap">
{monthNames[currentDate.getMonth()]} {currentDate.getFullYear()}
</h2>
<button
onClick={() => changeMonth(1)}
className="text-white hover:text-gray transition-colors text-[2vw] bg-ieee-black/40 w-[4vw] h-[4vw] rounded-[1vw] flex items-center justify-center"
>
</button>
</div>
</div>
</div>
{/* Main Calendar Body */}
<div className="bg-gradient-to-t from-ieee-blue-100/5 to-ieee-blue-100/25 rounded-[1.5vw] p-[1vw] relative">
{/* Week Days Header */}
<div className="grid grid-cols-7 gap-[0.5vw] mb-[1vw]">
{weekDays.map((day, index) => (
<div key={day} className="flex justify-center w-full">
<div
className={`text-white text-center font-semibold p-[0.5vw] text-[1.2vw] bg-ieee-black/60 w-full h-[4vw] flex items-center justify-center
${
index === 0
? "rounded-tl-[2vw] rounded-[0.5vw]"
: index === 6
? "rounded-tr-[2vw] rounded-[0.5vw]"
: "rounded-[0.5vw]"
}`}
>
{day}
</div>
</div>
))}
</div>
{/* Calendar Grid */}
<div className="grid grid-cols-7 gap-[0.5vw] relative">
{getDaysInMonth(currentDate).map((day, index) => (
<div
key={index}
className={`min-h-[10vw] p-[0.5vw] rounded relative ${
day ? "bg-white/5" : "bg-transparent"
} border border-white/10`}
>
{day && (
<>
<div className="text-white mb-[0.5vw] text-[1vw]">
{day.getDate()}
</div>
<div className="space-y-[0.5vw]">
{getEventsForDay(day).map((event, eventIndex) => (
<div
key={eventIndex}
className="text-[0.8vw] border border-gray-300 text-white p-[0.5vw] rounded truncate cursor-pointer hover:bg-white/10 transition-colors relative"
onMouseEnter={(e) => handleEventMouseEnter(event, e)}
onMouseLeave={handleEventMouseLeave}
>
{event.summary}
</div>
))}
</div>
</>
)}
</div>
))}
</div>
{/* Tooltip */}
{hoveredEvent && (
<div
className="fixed z-[9999] bg-ieee-blue-100 text-white p-[1vw] rounded-[0.5vw] shadow-xl border border-white/20 min-w-[15vw]"
style={{
left: `${tooltipPosition.x + 15}px`,
top: `${tooltipPosition.y + 15}px`,
}}
>
<h3 className="text-[1vw] font-semibold mb-[0.5vw]">
{hoveredEvent.event.summary}
</h3>
{hoveredEvent.event.description && (
<p className="text-[0.8vw] mb-[0.5vw] text-white/80">
{hoveredEvent.event.description}
</p>
)}
<div className="text-[0.8vw] text-white/90">
{hoveredEvent.event.start.dateTime ? (
<>
<p>
Start: {formatEventTime(hoveredEvent.event.start.dateTime)}
</p>
<p>End: {formatEventTime(hoveredEvent.event.end.dateTime)}</p>
</>
) : (
<p>All day event</p>
)}
{hoveredEvent.event.location && (
<p className="mt-[0.3vw]">
Location: {hoveredEvent.event.location}
</p>
)}
</div>
</div>
)}
</div>
</div>
);
};
export default Calendar;

View file

@ -0,0 +1,170 @@
import React, { useEffect, useState } from "react";
const UpcomingEvent = ({ name, location, date, time, delay, description }) => (
<div className="text-white w-[40vw] pl-[8%] md:border-l-[0.3vw] border-l-[0.5vw] border-white/70 pb-[5%] relative">
<p
data-inview
className={`animate-duration-500 animate-delay-${delay * 200} in-view:animate-fade-left py-[0.2%] px-[2%] w-fit border-[0.1vw] font-light rounded-full md:text-[1.3vw] text-[2.3vw]`}
>
{name}
</p>
<div
data-inview
className={`animate-duration-500 animate-delay-${delay * 200 + 100} in-view:animate-fade-left flex justify-between items-center min-w-[70%] w-fit md:text-[1.2vw] text-[2vw] my-[2%]`}
>
Location: {location}
{date && (
<>
<div className="bg-white h-[0.5vw] w-[0.5vw] rounded-full mx-[0.5vw]" />
<p>{date}</p>
</>
)}
{time && (
<>
<div className="bg-white h-[0.5vw] w-[0.5vw] rounded-full mx-[0.5vw]" />
<p>{time}</p>
</>
)}
</div>
<p
data-inview
className={`animate-duration-500 animate-delay-${delay * 200 + 200} in-view:animate-fade-left md:text-[1vw] text-[1.8vw] text-white/60`}
>
{description}
</p>
<div className="bg-ieee-yellow md:h-[1.2vw] h-[1.5vw] md:w-[1.2vw] w-[1.5vw] rounded-full absolute -top-[1.5%] -left-[2%]" />
</div>
);
const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
const [events, setEvents] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const apiKey = CALENDAR_API_KEY;
const calendarId = EVENT_CALENDAR_ID;
const userTimeZone = "America/Los_Angeles";
const loadGapiAndListEvents = async () => {
try {
console.log("Starting to load events...");
if (typeof window.gapi === "undefined") {
console.log("Loading GAPI script...");
await new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/api.js";
document.body.appendChild(script);
script.onload = () => {
console.log("GAPI script loaded");
window.gapi.load("client", resolve);
};
script.onerror = () => {
console.error("Failed to load GAPI script");
reject(new Error("Failed to load the Google API script."));
};
});
}
console.log("Initializing GAPI client...");
await window.gapi.client.init({
apiKey: apiKey,
discoveryDocs: [
"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
],
});
console.log("Fetching events...");
const response = await window.gapi.client.calendar.events.list({
calendarId: calendarId,
timeZone: userTimeZone,
singleEvents: true,
timeMin: new Date().toISOString(),
maxResults: 3,
orderBy: "startTime",
});
console.log("Response received:", response);
if (response.result.items) {
setEvents(response.result.items);
}
} catch (error) {
console.error("Detailed Error: ", error);
setError(error.message || "Failed to load events");
} finally {
setLoading(false);
}
};
if (!CALENDAR_API_KEY) {
setError("API key is missing");
setLoading(false);
return;
}
setLoading(true);
loadGapiAndListEvents();
}, [CALENDAR_API_KEY]);
if (!CALENDAR_API_KEY) {
return (
<div className="text-white">
Error: Calendar API key is not configured
</div>
);
}
return (
<div>
{error && <p className="text-white">Error: {error}</p>}
{!loading && !error && events.length === 0 && (
<UpcomingEvent
name="No Upcoming Events!"
location="¯\_(ツ)_/¯"
date=""
time=""
delay={0}
description="There are no upcoming events! Check back again soon :)
...or just wait for the entire page to load. This is here by default LOL"
/>
)}
{!loading && !error && events.length > 0 && (
<div>
{events.map((event, index) => {
const startDate = new Date(
event.start.dateTime || event.start.date,
);
const day = startDate.toLocaleDateString("en-US", {
weekday: "short",
});
const date = startDate.toLocaleDateString("en-US", {
day: "numeric",
month: "short",
year: "numeric",
});
const time = startDate.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});
return (
<UpcomingEvent
key={index}
name={event.summary || "No Title"}
location={event.location || "No location provided"}
date={`${day} ${date}`}
time={time}
delay={index}
description={event.description || "No description available."}
/>
);
})}
</div>
)}
</div>
);
};
export default EventList;

View file

@ -1,18 +1,17 @@
---
import { Image } from "astro:assets";
import eventbg from "../../images/eventbg.png";
import eventbg from "../../images/eventbg.webp";
import { LiaDotCircle } from "react-icons/lia";
---
<div class="w-full pt-[25vh] flex justify-center relative">
<div class="w-full md:pt-[5vw] pt-[10vw] flex justify-center relative">
<Image
src={eventbg}
alt="Event Page Background"
class="w-[45%] rounded-[2vw] aspect-[2/1] object-cover relative in-view:animate-fade-down opacity-0"
data-inview
class="md:w-[45%] w-[80%] rounded-[2vw] aspect-[2/1] object-cover"
/>
<div
class="absolute -bottom-[6%] left-[20%] flex items-center text-[3vw] py-[1.5%] px-[3%] text-white bg-ieee-black rounded-[2vw]"
class="absolute -bottom-[6%] md:left-[20%] left-[10%] flex items-center md:text-[3vw] text-[6vw] py-[1.5%] px-[3%] text-white bg-ieee-black rounded-[2vw]"
>
<LiaDotCircle className=" mr-[2vw] pt-[0.5%]" />
<p>EVENTS</p>

View file

@ -1,45 +1,28 @@
---
import UpcomingEvent from "./UpcomingEvent.astro";
import { LiaDotCircle } from "react-icons/lia";
import EventList from "./EventList.jsx";
const CALENDAR_API_KEY = import.meta.env.CALENDAR_API_KEY;
const EVENT_CALENDAR_ID = import.meta.env.EVENT_CALENDAR_ID;
---
<div class="flex ml-[15%] my-[10%]">
<div class="w-1/4 text-white pr-[5%] mr-[10%]">
<div class="w-[6vw] h-[0.3vw] bg-ieee-yellow rounded-full"/>
<div class="flex items-center text-[2vw] font-bold my-[10%]">
<div class="flex ml-[15%] md:my-[10%] my-[20%]">
<div class="md:w-1/4 w-[30%] text-white pr-[5%] mr-[10%]">
<div class="w-[6vw] h-[0.3vw] bg-ieee-yellow rounded-full"></div>
<div class="flex items-center md:text-[2vw] text-[4vw] font-bold my-[10%]">
<LiaDotCircle className=" mr-[1vw] text-[2.5vw]" />
<p>
Upcoming <br /> Events
</p>
</div>
<p class="text-[1.3vw] font-light">
<p class="md:text-[1.3vw] text-[2vw] font-light">
SCROLL DOWN TO SEE THE UPCOMING EVENTS FOR IEEE!
</p>
</div>
<div>
<UpcomingEvent
name="Beach Social"
location="La Jolla Cove"
date="Tue 9 Jun 2024"
time="2 pm"
delay="0"
description="Cursus nec orci pulvinar convallis mollis a diam. Nostra aptent praesent suscipit nisl dignissim consequat. Semper malesuada pharetra fusce; elementum maximus"
/>
<UpcomingEvent
name="Beach Social"
location="La Jolla Cove"
date="Tue 9 Jun 2024"
time="2 pm"
delay="300"
description="Cursus nec orci pulvinar convallis mollis a diam. Nostra aptent praesent suscipit nisl dignissim consequat. Semper malesuada pharetra fusce; elementum maximus"
/>
<UpcomingEvent
name="Beach Social"
location="La Jolla Cove"
date="Tue 9 Jun 2024"
time="2 pm"
delay="700"
description="Cursus nec orci pulvinar convallis mollis a diam. Nostra aptent praesent suscipit nisl dignissim consequat. Semper malesuada pharetra fusce; elementum maximus"
<EventList
client:load
CALENDAR_API_KEY={CALENDAR_API_KEY}
EVENT_CALENDAR_ID={EVENT_CALENDAR_ID}
/>
</div>
</div>

View file

@ -3,22 +3,32 @@ import Link from "next/link";
import { LiaDotCircle } from "react-icons/lia";
---
<div class="pt-[14vh] text-white w-full flex justify-center mb-[10vh]">
<div class="w-3/4 h-[40vh] flex justify-between flex-col">
<div class="flex items-center text-[3vw] pl-[5%] pt-[5%]">
<div
class="md:pt-[5vw] pt-[10vw] text-white w-full flex justify-center md:mb-[8vw] mb-[15vw]"
>
<div class="w-3/4 md:h-[25vw] h-[35vw] flex justify-between flex-col">
<div class="flex items-center md:text-[3vw] text-[4.5vw] pl-[5%] pt-[5%]">
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]" />
<p>
Contact Us
</p>
<p>Contact Us</p>
</div>
<p class="text-[1.25vw]">
The <a class=" text-ieee-yellow underline" href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6" target="_blank">IEEE Project Space</a> is an open-access, collaborative space located at EBU1-4710. Students can do homework or get access to basic electronic tools such as soldering stations, breadboard components, and Arduino and Raspberry PI parts!
<p class="md:text-[1.25vw] text-[2vw]">
The <a
class="text-ieee-yellow underline"
href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6"
target="_blank">IEEE Project Space</a
> is an open-access, collaborative space located at EBU1-4710. Students can
do homework or get access to basic electronic tools such as soldering stations,
breadboard components, and Arduino and Raspberry PI parts!
</p>
<div class="flex justify-end">
<Link data-inview href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6" target="_blank" className="in-view:animate-jump-in border-white/70 border-[0.1vw] py-[1%] px-[8%] rounded-[0.7vw] hover:text-ieee-yellow hover:border-ieee-yellow duration-300 text-[1.2vw]">
<Link
data-inview
href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6"
target="_blank"
className="in-view:animate-jump-in border-white/70 border-[0.1vw] py-[1%] px-[8%] rounded-[0.7vw] hover:text-ieee-yellow hover:border-ieee-yellow duration-300 md:text-[1.2vw] text-[2vw]"
>
DISCORD
</Link>
</div>
</div>
</div>

View file

@ -0,0 +1,20 @@
---
---
<div
data-inview
class="flex flex-col items-center md:w-[40vw] w-[100vw] h-[100vw] md:h-[40vw] my-[10%] in-view:animate-fade-down"
>
<p class="text-ieee-yellow md:text-[1.2vw] text-[2.5vw]">Each officer has their own OAH</p>
<p class="text-white md:text-[2.5vw] text-[4.5vw] my-[2%]">Check out our calendar!</p>
<iframe
class="w-[90%] rounded-[1.5vw]"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3350.627565860723!2d-117.23806952372503!3d32.881572078634505!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x80dc06c3689b4f99%3A0xdf55f97f07f34d4f!2sIrwin%20%26%20Joan%20Jacobs%20School%20of%20Engineering!5e0!3m2!1sen!2sus!4v1736755644414!5m2!1sen!2sus"
width="600"
height="450"
style="border:0;"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"></iframe>
</div>

View file

@ -1,8 +1,9 @@
---
import OH from "./OH.astro"
import OAH from "./OAH.astro";
import BuildingLocation from "./BuildingLocation.astro";
---
<div class="w-full flex justify-evenly px-[10%]">
<OH title="Check out our calendar!" subtitle="Each officer has their own OAH" image="/calendar.png" />
<OH title="Check out our location!" subtitle="We are located in EBU1-4710" image="/map.png" />
<div class="w-full flex flex-col md:flex-row items-center md:justify-evenly px-[10%]">
<OAH />
<BuildingLocation />
</div>

View file

@ -6,16 +6,16 @@ import { IoMdCalendar } from "react-icons/io";
import { RiRobot2Fill } from "react-icons/ri";
const {image, text, link, delay} = Astro.props;
---
<div data-inview class={`w-[15vw] relative group in-view:animate-fade-up animate-delay-${delay} animate-duration-1000`}>
<div data-inview class={` animate-ease-in-out md:w-[15vw] w-[24vw] relative group in-view:animate-fade-up animate-delay-${delay} animate-duration-1000`}>
<img src={image} alt="involvement background" class="opacity-70 aspect-[230/425] object-cover rounded-[2vw] group-hover:opacity-50 duration-300"/>
<Link
href={link}
target={text==="H.A.R.D. HACK"? "_blank":"_self"}
className="absolute top-0 w-[15vw] pt-[5%] aspect-[230/425] flex flex-col justify-between"
className="absolute top-0 md:w-[15vw] w-[25vw] pt-[5%] aspect-[230/425] flex flex-col justify-between"
>
<div class="w-full flex justify-end pr-[5%]">
<div class="bg-white w-fit rounded-full aspect-square p-[0.5vw] text-ieee-black text-[2vw]">
<div class="w-full flex justify-end md:pr-[5%] pr-[2vw]">
<div class="bg-white w-fit rounded-full aspect-square p-[0.5vw] text-ieee-black text-[4.5vw] md:text-[2vw]">
{
text === "PROJECTS"? <RiRobot2Fill/>:
text === "EVENTS"? <IoMdCalendar/>:
@ -24,16 +24,16 @@ const {image, text, link, delay} = Astro.props;
</div>
</div>
<div class="px-[3%] text-white w-full bg-gradient-to-t from-black via-black to-transparent rounded-b-[2vw] pt-[30%] pb-[5%]">
<div class="text-[1.1vw] duration-300 flex w-full px-[3%] justify-between items-end">
<div class="px-[3%] text-white w-full bg-gradient-to-t from-black via-black to-transparent rounded-b-[2vw] pt-[20vw] pb-[3vw] md:pt-[30%] md:pb-[5%]">
<div class="text-[2vw] md:text-[1.1vw] duration-300 flex w-full px-[3%] justify-between items-end">
<p class="pt-[3%] pb-[2%] px-[10%] border-[0.1vw] border-white rounded-full group-hover:text-ieee-yellow group-hover:border-ieee-yellow duration-300 font-light">
{text}
</p>
<GoArrowDownRight className="text-[3vw] leading-none group-hover:text-ieee-yellow"/>
<GoArrowDownRight className="text-[5vw] md:text-[3vw] leading-none group-hover:text-ieee-yellow"/>
</div>
{text === "H.A.R.D. HACK" &&
<p class="text-[1vw] text-center pt-[10%] group-hover:text-ieee-yellow duration-300">
<p class="text-[1.8vw] md:text-[1vw] text-center pt-[10%] group-hover:text-ieee-yellow duration-300">
UC San Diegos largest
hardware focused hackathon
hold by IEEE UCSD, HKN, and TNT

View file

@ -2,8 +2,8 @@
import Involvement from "./Involvement.astro";
import involve from "../../data/involve.json";
---
<div class="pl-[10%] pr-[6%] flex items-center mb-[10%]">
<div class="flex w-3/5 justify-between">
<div class="pl-[10%] pr-[6%] flex md:items-center md:mb-[10%] mb-[30vw] mt-[20vw] md:mt-0 flex-col-reverse md:flex-row">
<div class="flex md:w-3/5 w-[95%] justify-between">
{involve.map((item)=>(
<Involvement
text = {item.text}
@ -14,11 +14,11 @@ import involve from "../../data/involve.json";
))}
</div>
<div class="w-2/5 flex flex-col px-[5%]">
<p class="text-ieee-yellow text-[1.2vw] mb-[5%]">
Get involve in international IEEE
<div class="md:w-2/5 w-4/5 flex flex-col px-[5%] pb-[10vw] md:pb-0">
<p class="text-ieee-yellow md:text-[1.2vw] text-[2.5vw] mb-[5%]">
Get involve in IEEE @ UCSD
</p>
<p class="text-white text-[2vw] font-bold">
<p class="text-white md:text-[2vw] text-[3vw] font-bold">
How To Keep Up With And Get Engaged With IEEE at UCSD
</p>
</div>

View file

@ -3,22 +3,35 @@ import Link from "next/link";
import { LiaDotCircle } from "react-icons/lia";
---
<div class="pt-[14vh] text-white w-full flex justify-center mb-[20vh]">
<div class="w-3/4 h-[40vh] flex justify-between flex-col">
<div data-inview class="flex items-center text-[3vw] pl-[5%] pt-[5%] in-view:animate-fade-right">
<div class="text-white w-full flex justify-center mb-[10vw]">
<div class="w-3/4 md:h-[20vw] h-[40vw] flex justify-between flex-col">
<div
data-inview
class="animate-ease-in-out flex items-center text-[6vw] md:text-[3vw] pl-[5%] pt-[5%] in-view:animate-fade-right"
>
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]" />
<p>
Join Us
</p>
<p>Join Us</p>
</div>
<p class="text-[1.25vw]">
The <a class=" text-ieee-yellow underline" href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6" target="_blank">IEEE Project Space</a> is an open-access, collaborative space located at EBU1-4710. Students can do homework or get access to basic electronic tools such as soldering stations, breadboard components, and Arduino and Raspberry PI parts!
<p class="text-[2.2vw] md:text-[1.25vw]">
The <a
class="text-ieee-yellow underline"
href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6"
target="_blank">IEEE Project Space</a
> is an open-access, collaborative space located at EBU1-4710. Students can
do homework or get access to basic electronic tools such as soldering stations,
breadboard components, and Arduino and Raspberry PI parts!
</p>
<div data-inview class="flex justify-end in-view:animate-fade-up">
<Link href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6" target="_blank" className="text-[1.2vw] border-white/70 border-[0.1vw] py-[1%] px-[8%] rounded-[0.7vw] hover:text-ieee-yellow hover:border-ieee-yellow duration-300">
<div
data-inview
class="animate-ease-in-out flex justify-end in-view:animate-fade-up"
>
<Link
href="https://maps.app.goo.gl/y4RwNCkoKBEHGHsv6"
target="_blank"
className="text-[2.5vw] md:text-[1.2vw] border-white/70 border-[0.1vw] py-[1%] px-[8%] rounded-[0.7vw] hover:text-ieee-yellow hover:border-ieee-yellow duration-300"
>
JOIN
</Link>
</div>
</div>
</div>

View file

@ -0,0 +1,19 @@
---
---
<div
data-inview
class="flex flex-col items-center md:w-[40vw] w-[100vw] h-[100vw] md:h-[40vw] my-[10%] in-view:animate-fade-down"
>
<p class="text-ieee-yellow md:text-[1.2vw] text-[2.5vw]">Each officer has their own OAH</p>
<p class="text-white md:text-[2.5vw] text-[4.5vw] my-[2%]">Check out our calendar!</p>
<iframe
class="w-[90%] rounded-[1.5vw]"
src="https://calendar.google.com/calendar/embed?src=c_62493071bab19c7c60d103460604dc7b3b569ffc1e58a42617978f626dff02ac%40group.calendar.google.com&ctz=America%2FLos_Angeles"
style="border: 0"
width="600"
height="450"
frameborder="0"
scrolling="no"></iframe>
</div>

View file

@ -1,13 +0,0 @@
---
const {title, subtitle, image} = Astro.props;
---
<div data-inview class="flex flex-col items-center w-[40vw] my-[10%] in-view:animate-fade-down">
<p class="text-ieee-yellow text-[1.2vw]">
{subtitle}
</p>
<p class="text-white text-[2.5vw] my-[2%]">
{title}
</p>
<img src={image} alt="Office hours" class="object-cover aspect-[620/408] w-[90%] rounded-[2vw]" />
</div>

View file

@ -2,19 +2,19 @@ import Link from "next/link";
const Resource = ({icon, title, text, link}) => {
return (
<div class="text-white flex w-[30vw] items-center">
<div class = "mr-[1vw] bg-gradient-radial from-ieee-blue-300 via-ieee-black to-ieee-black rounded-full text-[6.5vw] aspect-square w-[12vw] flex justify-center items-center">
<div class="text-white flex md:w-[30vw] w-[40vw] items-center">
<div class = "mr-[1vw] bg-gradient-radial from-ieee-blue-300 via-ieee-black to-ieee-black rounded-full text-[8vw] md:text-[6.5vw] aspect-square w-[12vw] flex justify-center items-center">
{icon}
</div>
<div class="w-[24vw]">
<p class = "text-[1.8vw] mb-[2vh] font-extralight">
<div class="md:w-[24vw] w-[27vw] ">
<p class = "md:text-[1.8vw] text-[2.5vw] mb-[2vh] font-extralight">
{title}
</p>
<p class = "text-[1vw] mb-[1vh] font-light">
<p class = "md:text-[1vw] text-[1.8vw] mb-[1vh] font-light">
{text}
</p>
<div class="flex justify-end mt-[5%]">
<Link href={link} target="_blank" className=" text-[1.1vw] font-extralight border-white/70 border-[0.1vw] py-[1%] px-[11%] rounded-[0.5vw] cursor-pointer hover:text-ieee-yellow hover:border-ieee-yellow duration-300">
<Link href={link} target="_blank" className=" md:text-[1.1vw] text-[2vw] font-extralight border-white/70 border-[0.1vw] py-[1%] px-[11%] rounded-[0.5vw] cursor-pointer hover:text-ieee-yellow hover:border-ieee-yellow duration-300">
VIEW
</Link>
</div>

View file

@ -1,29 +1,29 @@
import Resource from "./Resource.jsx"
import { LiaDotCircle } from "react-icons/lia";
import { RiSlideshowLine } from "react-icons/ri";
import { BiMoviePlay } from "react-icons/bi";
import { IoMdGlobe } from "react-icons/io";
const Resources = () => {
return (
<div class = "text-white w-full flex flex-col items-center h-[55vh] justify-center">
<div class = "text-[2.5vw] flex items-center">
<div class = "text-white w-full flex flex-col items-center justify-center mb-[20vw] md:mb-[5vw]">
<div class = "text-[4.5vw] md:text-[2.5vw] flex items-center">
<LiaDotCircle className = "mr-[1vw] pt-[0.5%]" />
<p>
Member Resources
</p>
</div>
<div class = " w-[90%] flex justify-evenly mt-[9vh]">
<div class = "md:w-[90%] w-full flex justify-evenly mt-[5vw]">
<Resource
icon = <RiSlideshowLine/>
title = "Workshop Slides"
text = "Hac at maecenas maximus faucibus venenatis blandit. Netus elit fusce a tortor"
text = "Find our database of workshop slides here."
link = "http://www.google.com"
/>
<Resource
icon = <BiMoviePlay/>
title = "Workshop Videos"
text = "Hac at maecenas maximus faucibus venenatis blandit. Netus elit fusce a tortor"
link = "http://www.google.com"
icon = <IoMdGlobe/>
title = "International IEEE"
text = "Our parent organization provides variety of events including project sponsorship, IEEE DataPort dataset database, and renowned student contests."
link = "https://www.ieee.org/"
/>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show more