fix conflict
BIN
bun.lockb
4
nixpacks.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[phases.setup]
|
||||||
|
nixPkgs = ["nodejs_18", "bun"]
|
||||||
|
aptPkgs = ["curl", "wget"]
|
||||||
|
|
BIN
public/404.png
Before Width: | Height: | Size: 2 MiB |
BIN
public/404.webp
Normal file
After Width: | Height: | Size: 431 KiB |
Before Width: | Height: | Size: 112 KiB |
BIN
public/calendar.webp
Normal file
After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 203 KiB |
BIN
public/halloween.webp
Normal file
After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 308 KiB |
BIN
public/hardhack.webp
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
public/map.png
Before Width: | Height: | Size: 74 KiB |
BIN
public/map.webp
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.3 MiB |
BIN
public/officers/akhil.webp
Normal file
After Width: | Height: | Size: 1,020 KiB |
Before Width: | Height: | Size: 1.1 MiB |
BIN
public/officers/allie.webp
Normal file
After Width: | Height: | Size: 987 KiB |
Before Width: | Height: | Size: 949 KiB |
BIN
public/officers/andy.webp
Normal file
After Width: | Height: | Size: 741 KiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/officers/anika.webp
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.5 MiB |
BIN
public/officers/anu.webp
Normal file
After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/officers/ashlee.webp
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 699 KiB |
BIN
public/officers/charles.webp
Normal file
After Width: | Height: | Size: 540 KiB |
Before Width: | Height: | Size: 1.5 MiB |
BIN
public/officers/christine.webp
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.8 MiB |
BIN
public/officers/dhruv.webp
Normal file
After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/officers/dihan.webp
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.2 MiB |
BIN
public/officers/emma.webp
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.3 MiB |
BIN
public/officers/erik.webp
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.2 MiB |
BIN
public/officers/jonathan.webp
Normal file
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.3 MiB |
BIN
public/officers/lauren.webp
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.5 MiB |
BIN
public/officers/lisa.webp
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.5 MiB |
BIN
public/officers/philip.webp
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.2 MiB |
BIN
public/officers/pranav.webp
Normal file
After Width: | Height: | Size: 943 KiB |
Before Width: | Height: | Size: 1.1 MiB |
BIN
public/officers/rafaella.webp
Normal file
After Width: | Height: | Size: 987 KiB |
Before Width: | Height: | Size: 1.7 MiB |
BIN
public/officers/raymond.webp
Normal file
After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1 MiB |
BIN
public/officers/ridhi.webp
Normal file
After Width: | Height: | Size: 973 KiB |
Before Width: | Height: | Size: 2.1 MiB |
BIN
public/officers/rohil.webp
Normal file
After Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/officers/shing.webp
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/officers/shipra.webp
Normal file
After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 235 KiB |
BIN
public/officers/stella.webp
Normal file
After Width: | Height: | Size: 209 KiB |
Before Width: | Height: | Size: 82 KiB |
BIN
public/officers/steph.webp
Normal file
After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 1.7 MiB |
BIN
public/officers/terri.webp
Normal file
After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 205 KiB |
BIN
public/officers/zarif.webp
Normal file
After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 1.5 MiB |
BIN
public/project.webp
Normal file
After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 4.2 MiB |
BIN
public/robocup.webp
Normal file
After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 216 KiB |
BIN
public/signal.webp
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 60 KiB |
BIN
public/supercomp.webp
Normal file
After Width: | Height: | Size: 42 KiB |
|
@ -1,3 +1,166 @@
|
||||||
---
|
---
|
||||||
|
const { filters, currentFilter } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
---
|
<div class="inline-flex border border-white/20 rounded-full p-1 relative">
|
||||||
|
<div
|
||||||
|
id="slider"
|
||||||
|
class="absolute h-[calc(100%-8px)] bg-[#FFB81C] rounded-full transition-none"
|
||||||
|
style="left: 4px;"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
filters.map((filter) => (
|
||||||
|
<button
|
||||||
|
data-filter={filter}
|
||||||
|
class={`px-6 py-2 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>
|
||||||
|
|
|
@ -2,31 +2,56 @@
|
||||||
import { FaGear } from "react-icons/fa6";
|
import { FaGear } from "react-icons/fa6";
|
||||||
import { MdEmail } from "react-icons/md";
|
import { MdEmail } from "react-icons/md";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { Image } from "astro:assets";
|
||||||
const { name, position, picture, email } = Astro.props;
|
const { name, position, picture, email } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="text-white">
|
<div class="text-white">
|
||||||
<div class="text-ieee-yellow">
|
<div class="text-ieee-yellow">
|
||||||
<Link href={`mailto:${email}`} className = "flex items-center ml-[3%] py-[0.5vh] group">
|
<Link
|
||||||
<MdEmail className = "md:text-[1.5vw] text-[2.5vw] mr-[0.5%] group-hover:scale-110 group-hover:opacity-70 duration-300"/>
|
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]">
|
<p class="md:text-[0.8vw] text-[2vw]">
|
||||||
{email}
|
{email}
|
||||||
</p>
|
</p>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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">
|
<div
|
||||||
<img src ={picture} alt = "officer" class = "md:w-[18vw] w-[31vw] md:rounded-[1.5vw] rounded-[3vw] mt-[5%] mb-[3%]" >
|
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"
|
||||||
<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]">
|
>
|
||||||
|
<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 />
|
<FaGear />
|
||||||
</div>
|
</div>
|
||||||
<div class = "w-full flex justify-between px-[7%]">
|
<p
|
||||||
<p data-inview class = " in-view:animate-fade-right md:text-[2vw] text-[3.5vw] font-light md:leading-[2.5vw] leading-[5vw]">
|
data-inview
|
||||||
|
class="in-view:animate-fade-right md:text-[2vw] text-[3.5vw] font-light md:leading-[2.5vw] leading-[5vw]"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
data-inview
|
||||||
|
class="in-view:animate-fade-right text-[2vw] font-light md:leading-[3vh] leading-[1.5vh]"
|
||||||
|
>
|
||||||
{name}
|
{name}
|
||||||
</p>
|
</p>
|
||||||
<div data-inview class = "md:mt-[0.5vw] mt-[1.5vw] in-view:animate-fade-up md:text-[0.8vw] text-[1.5vw] md:w-[8vw] w-[15vw] 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-[20vw] md:w-[10vw] border-[0.11vw] border-white/90 rounded-full p-[0.5%] h-fit text-center"
|
||||||
|
>
|
||||||
{position}
|
{position}
|
||||||
</div>
|
</div>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
|
@ -1,19 +1,31 @@
|
||||||
---
|
---
|
||||||
import about from "../../images/about.png";
|
import about from "../../images/about.webp";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import neko from "../../images/neko.png";
|
import neko from "../../images/neko.webp";
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import Officer from "../board/Officer.astro";
|
import Officer from "../board/Officer.astro";
|
||||||
|
import Filter from "../board/Filter.astro";
|
||||||
import officers from "../../data/officers.json";
|
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 md:mt-[10vw] mt-[20vw] mb-[10vh]">
|
<div
|
||||||
<div data-inview class="relative w-[40vw] md:w-[21vw] in-view:animate-fade-down">
|
class="text-white flex flex-col items-center md:mt-[10vw] mt-[20vw] 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={about} alt="About background image" />
|
||||||
<Image
|
<Image
|
||||||
src={neko}
|
src={neko}
|
||||||
alt="About image"
|
alt="About image"
|
||||||
class="absolute top-[10%] left-[16%] aspect-[399/491] object-cover w-[27vw] md:w-[14vw] rounded-[2vw]"
|
class="absolute top-[10%] left-[16%] aspect-[399/491] object-cover w-[27vw] md:ww-[14vw] rounded-[2vw]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -22,19 +34,31 @@ import officers from "../../data/officers.json";
|
||||||
<p>MEET THE BOARD</p>
|
<p>MEET THE BOARD</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="md:text-[1.3vw] text-[2.5vw] md:w-[56%] w-[70%] my-[3%] font-extralight text-center">
|
<p
|
||||||
Our board comprises 31 students of varying majors, colleges, and interests! Feel free to reach out for any questions about our position or experiences.
|
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>
|
</p>
|
||||||
|
|
||||||
<div class="grid gap-[3vw] md:grid-cols-3 grid-cols-2 mt-[10vh]">
|
<Filter filters={types} currentFilter={currentFilter} />
|
||||||
|
|
||||||
|
<div class="grid gap-[3vw] md:grid-cols-3 grid-cols-2 mt-[2vh]">
|
||||||
{
|
{
|
||||||
officers.map((officer) => (
|
officers.map((officer) => (
|
||||||
|
<div
|
||||||
|
data-officer
|
||||||
|
data-types={JSON.stringify(officer.type)}
|
||||||
|
style="opacity: 0; visibility: hidden"
|
||||||
|
>
|
||||||
<Officer
|
<Officer
|
||||||
name={officer.name}
|
name={officer.name}
|
||||||
position={officer.position}
|
position={officer.position}
|
||||||
picture={officer.picture}
|
picture={officer.picture}
|
||||||
email={officer.email}
|
email={officer.email}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
---
|
---
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import jellyfish from "../../images/jellyfish.png";
|
import jellyfish from "../../images/jellyfish.webp";
|
||||||
import { FaDiscord } from "react-icons/fa";
|
import { FaDiscord } from "react-icons/fa";
|
||||||
import { RiInstagramFill } from "react-icons/ri";
|
import { RiInstagramFill } from "react-icons/ri";
|
||||||
import { MdEmail } from "react-icons/md";
|
import { MdEmail } from "react-icons/md";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="text-white flex flex-col items-center md:h-[35vw] h-[60vw] justify-between">
|
<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]">
|
<div class="flex items-center text-[4.5vw] md:text-[2.5vw]">
|
||||||
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]" />
|
<LiaDotCircle className=" mr-[1vw] pt-[0.5%]" />
|
||||||
<p>Social Media</p>
|
<p>Social Media</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="md:w-1/3 w-3/5 text-center text-[2vw] md:text-[1.2vw] pb-[5%]">
|
<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.
|
Stay connected with us on Discord, Facebook, and Instagram! We regularly
|
||||||
|
post information on upcoming events and competitions.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
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"
|
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 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">
|
<div
|
||||||
|
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"
|
||||||
|
>
|
||||||
<Link
|
<Link
|
||||||
href="https://www.instagram.com/ieee.ucsd"
|
href="https://www.instagram.com/ieee.ucsd"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -32,7 +38,9 @@ import Link from "next/link";
|
||||||
>
|
>
|
||||||
<RiInstagramFill />
|
<RiInstagramFill />
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[2vw] md:text-[1.3vw] font-semibold">Instagram</p>
|
<p class="text-[2vw] md:text-[1.3vw] font-semibold">
|
||||||
|
Instagram
|
||||||
|
</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import eventbg from "../../images/eventbg.png";
|
import eventbg from "../../images/eventbg.webp";
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
import about from "../../images/about.png";
|
import about from "../../images/about.webp";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import about2 from "../../images/about2.png";
|
import about2 from "../../images/about2.webp";
|
||||||
import about3 from "../../images/about3.png";
|
import about3 from "../../images/about3.webp";
|
||||||
import about4 from "../../images/about4.png";
|
import about4 from "../../images/about4.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -13,7 +13,11 @@ import about4 from "../../images/about4.png";
|
||||||
>
|
>
|
||||||
<div class="w-1/2 flex justify-center pr-[5%] relative h-full">
|
<div class="w-1/2 flex justify-center pr-[5%] relative h-full">
|
||||||
<div class="relative w-[35vw]">
|
<div class="relative w-[35vw]">
|
||||||
<Image src={about} alt="About background image" class="md:visible invisible" />
|
<Image
|
||||||
|
src={about}
|
||||||
|
alt="About background image"
|
||||||
|
class="md:visible invisible"
|
||||||
|
/>
|
||||||
<Image
|
<Image
|
||||||
src={about4}
|
src={about4}
|
||||||
alt="About image"
|
alt="About image"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import landingimg from "../../images/landing.png";
|
import landingimg from "../../images/landing.webp";
|
||||||
import { FaDiscord } from "react-icons/fa";
|
import { FaDiscord } from "react-icons/fa";
|
||||||
import { RiInstagramFill } from "react-icons/ri";
|
import { RiInstagramFill } from "react-icons/ri";
|
||||||
import { MdEmail } from "react-icons/md";
|
import { MdEmail } from "react-icons/md";
|
||||||
|
@ -11,18 +11,30 @@ import { MdEmail } from "react-icons/md";
|
||||||
<div
|
<div
|
||||||
class="md:pt-[5%] pt-[6%] bg-gradient-to-t to-ieee-blue-100/30 p-[5vw] via-ieee-black from-ieee-black md:w-[53%] w-[60%] md:h-[40vw] h-[60vw] border-white/70 border-[0.1vw] rounded-[3vw]"
|
class="md:pt-[5%] pt-[6%] bg-gradient-to-t to-ieee-blue-100/30 p-[5vw] via-ieee-black from-ieee-black md:w-[53%] w-[60%] md:h-[40vw] h-[60vw] border-white/70 border-[0.1vw] rounded-[3vw]"
|
||||||
>
|
>
|
||||||
<p data-inview class="animate-ease-in-out text-ieee-yellow font-bold text-[3.5vw] md:text-[2.2vw] mb-[3%] in-view:animate-flip-down">
|
<p
|
||||||
|
data-inview
|
||||||
|
class="animate-ease-in-out text-ieee-yellow font-bold text-[3.5vw] md:text-[2.2vw] mb-[3%] in-view:animate-flip-down"
|
||||||
|
>
|
||||||
UC San Diego IEEE
|
UC San Diego IEEE
|
||||||
</p>
|
</p>
|
||||||
<p data-inview class="animate-ease-in-out font-bold text-[3.6vw] md:text-[2.8vw] text-white mb-[6%] in-view:animate-fade-right">
|
<p
|
||||||
|
data-inview
|
||||||
|
class="animate-ease-in-out font-bold text-[3.6vw] md:text-[2.8vw] text-white mb-[6%] in-view:animate-fade-right"
|
||||||
|
>
|
||||||
Join one of the largest IEEE student branch in the US!
|
Join one of the largest IEEE student branch in the US!
|
||||||
</p>
|
</p>
|
||||||
<p class="text-white font-light text-[2vw] md:text-[1.3vw]">
|
<p class="text-white font-light text-[2vw] md:text-[1.3vw]">
|
||||||
IEEE @ UCSD is a pre-professional organization aiming to empower engineers with practical experience through hands-on project opportunities, insightful workshops, and panels with industry professionals. We are a branch organization of the International IEEE organization.
|
IEEE @ UCSD is a pre-professional organization aiming to empower
|
||||||
|
engineers with practical experience through hands-on project
|
||||||
|
opportunities, insightful workshops, and panels with industry
|
||||||
|
professionals. We are a branch organization of the International
|
||||||
|
IEEE organization.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="flex justify-end w-full mt-[6%]">
|
<div class="flex justify-end w-full mt-[6%]">
|
||||||
<div class="text-white text-[3.5vw] md:text-[2.5vw] w-1/2 flex justify-between">
|
<div
|
||||||
|
class="text-white text-[3.5vw] md:text-[2.5vw] w-1/2 flex justify-between"
|
||||||
|
>
|
||||||
<Link
|
<Link
|
||||||
href="https://www.instagram.com/ieee.ucsd"
|
href="https://www.instagram.com/ieee.ucsd"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -51,6 +63,10 @@ import { MdEmail } from "react-icons/md";
|
||||||
<div
|
<div
|
||||||
class="md:w-[46%] w-[40%] md:h-[40vw] h-[60vw] border-white/70 border-[0.1vw] rounded-[3vw] bg-gradient-to-b to-ieee-blue-100/60 from-ieee-black"
|
class="md:w-[46%] w-[40%] md:h-[40vw] h-[60vw] border-white/70 border-[0.1vw] rounded-[3vw] bg-gradient-to-b to-ieee-blue-100/60 from-ieee-black"
|
||||||
>
|
>
|
||||||
<Image src={landingimg} alt="circuit" class="w-[95%] md:h-[40vw] h-[60vw] object-contain" />
|
<Image
|
||||||
|
src={landingimg}
|
||||||
|
alt="circuit"
|
||||||
|
class="w-[95%] md:h-[40vw] h-[60vw] object-contain"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,20 +3,23 @@ import annualProjects from "../../data/annualProjects.json";
|
||||||
import { FaGear } from "react-icons/fa6";
|
import { FaGear } from "react-icons/fa6";
|
||||||
import { GoArrowDownRight } from "react-icons/go";
|
import { GoArrowDownRight } from "react-icons/go";
|
||||||
import { IoIosArrowDroprightCircle } from "react-icons/io";
|
import { IoIosArrowDroprightCircle } from "react-icons/io";
|
||||||
|
import { Image } from "astro:assets";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex gap-[1.5vw] h-[50vh]">
|
<div class="flex gap-[1.5vw] h-[50vh]">
|
||||||
{
|
{
|
||||||
Object.entries(annualProjects).map(
|
Object.entries(annualProjects).map(([title, project], index) => (
|
||||||
([title, project], index) => (
|
|
||||||
<a
|
<a
|
||||||
href={project.url || "#"}
|
href={project.url || "#"}
|
||||||
class={`project-card group relative flex-1 rounded-[1.5vw] overflow-hidden transition-all duration-500 ease-in-out md:hover:flex-[2] cursor-pointer ${index === 0 ? "expanded" : ""}`}
|
class={`project-card group relative flex-1 rounded-[1.5vw] overflow-hidden transition-all duration-500 ease-in-out md:hover:flex-[2] cursor-pointer ${index === 0 ? "expanded" : ""}`}
|
||||||
data-project={index + 1}
|
data-project={index + 1}
|
||||||
target={title === "Supercomputing" ? "_blank" : "_self"}
|
target={title === "Supercomputing" ? "_blank" : "_self"}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
src={project.image}
|
src={project.image}
|
||||||
alt={`${title} Project`}
|
alt={`${title} Project`}
|
||||||
|
width={668}
|
||||||
|
height={990}
|
||||||
class="opacity-70 w-full h-full object-cover rounded-[1.5vw] aspect-[2/3] transition-transform duration-500 ease-in-out md:group-hover:scale-110"
|
class="opacity-70 w-full h-full object-cover rounded-[1.5vw] aspect-[2/3] transition-transform duration-500 ease-in-out md:group-hover:scale-110"
|
||||||
/>
|
/>
|
||||||
<div class="absolute flex items-end bottom-0 left-0 px-[5%] pb-[5%] pt-[17%] bg-gradient-to-b from-transparent to-black via-black rounded-b-[1.5vw] text-white z-10 w-full transition-transform duration-300 md:[.expanded_&]:pb-[5%]">
|
<div class="absolute flex items-end bottom-0 left-0 px-[5%] pb-[5%] pt-[17%] bg-gradient-to-b from-transparent to-black via-black rounded-b-[1.5vw] text-white z-10 w-full transition-transform duration-300 md:[.expanded_&]:pb-[5%]">
|
||||||
|
@ -41,8 +44,7 @@ import { IoIosArrowDroprightCircle } from "react-icons/io";
|
||||||
<FaGear />
|
<FaGear />
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
)
|
))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import qp from "../../images/qp.png";
|
import qp from "../../images/qp.webp";
|
||||||
import { IoIosArrowDroprightCircle } from "react-icons/io";
|
import { IoIosArrowDroprightCircle } from "react-icons/io";
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import Subtitle from "../core/Subtitle.astro";
|
import Subtitle from "../core/Subtitle.astro";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import qp from "../../images/qp.png";
|
import qp from "../../images/qp.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex flex-col items-center pb-[5%]">
|
<div class="flex flex-col items-center pb-[5%]">
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import mentorship from "../../images/mentorship.png";
|
import mentorship from "../../images/mentorship.webp";
|
||||||
import jonathan from "../../images/about3.png";
|
import jonathan from "../../images/about3.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex justify-center mb-[10%]">
|
<div class="flex justify-center mb-[10%]">
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { LiaDotCircle } from "react-icons/lia";
|
import { LiaDotCircle } from "react-icons/lia";
|
||||||
import mentorship from "../../images/joinbg.png";
|
import mentorship from "../../images/joinbg.webp";
|
||||||
import jonathan from "../../images/about3.png";
|
import jonathan from "../../images/about3.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex justify-center mt-[10%] mb-[3%]">
|
<div class="flex justify-center mt-[10%] mb-[3%]">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { GoArrowDownRight } from "react-icons/go";
|
import { GoArrowDownRight } from "react-icons/go";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import robocup from "../../images/robocup.png";
|
import robocup from "../../images/robocup.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex flex-col items-center relative my-[10%]">
|
<div class="flex flex-col items-center relative my-[10%]">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import Title from "../core/Title.astro";
|
import Title from "../core/Title.astro";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import model from "../../images/model.png";
|
import model from "../../images/model.webp";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -4,19 +4,13 @@ import { LuBrainCircuit } from "react-icons/lu";
|
||||||
const { title, list } = Astro.props;
|
const { title, list } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="px-[10%] relative flex flex-col justify-center items-center w-[20vw] h-[43vh] bg-gradient-to-b from-ieee-blue-100/25 to-ieee-black backdrop-blur rounded-[2vw] border-white/40 border-[0.1vw]">
|
<div
|
||||||
|
class="px-[10%] flex flex-col justify-center items-center w-[20vw] h-[38vh] bg-gradient-to-b from-ieee-blue-100/25 to-ieee-black backdrop-blur rounded-[2vw] border-white/40 border-[0.1vw]"
|
||||||
|
>
|
||||||
<p class="text-[1.5vw] mb-[10%] font-semibold pt-[10%]">
|
<p class="text-[1.5vw] mb-[10%] font-semibold pt-[10%]">
|
||||||
{title}
|
{title}
|
||||||
</p>
|
</p>
|
||||||
<ul class="text-[1vw] font-light">
|
<ul class="text-[1vw] font-light">
|
||||||
{list.map((item)=>(
|
{list.map((item: string) => <li>• {item}</li>)}
|
||||||
<li>• {item}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="-top-[10%] w-fit p-[5%] shadow-ieee-blue-300 text-[3.2vw] bg-gradient-to-b from-ieee-blue-100 to-ieee-blue-300 rounded-full absolute">
|
|
||||||
{title==="Mechanical" && <FaGear />}
|
|
||||||
{title==="Electrical" && <FaMicrochip />}
|
|
||||||
{title==="AI" && <LuBrainCircuit />}
|
|
||||||
{title==="Embedded" && <FaCode />}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
|
@ -1,13 +1,243 @@
|
||||||
---
|
---
|
||||||
import Subtitle from "../core/Subtitle.astro";
|
import Subtitle from "../core/Subtitle.astro";
|
||||||
import Subteam from "./Subteam.astro";
|
import Subteam from "./Subteam.astro";
|
||||||
import subteams from "../../data/subteams.json"
|
import subteams from "../../data/subteams.json";
|
||||||
|
import { IoIosArrowBack, IoIosArrowForward } from "react-icons/io";
|
||||||
|
import { FaGear, FaMicrochip, FaCode } from "react-icons/fa6";
|
||||||
|
import { LuBrainCircuit } from "react-icons/lu";
|
||||||
|
|
||||||
|
// duplicate the array 3 times for smoother looping
|
||||||
|
const duplicatedSubteams = [...subteams, ...subteams, ...subteams];
|
||||||
|
const centerIndex = Math.floor(subteams.length); // center in the middle
|
||||||
---
|
---
|
||||||
<div class="flex flex-col items-center my-[10%]">
|
|
||||||
|
<div class="flex flex-col items-center my-[10%] relative">
|
||||||
<Subtitle title="Subteams" />
|
<Subtitle title="Subteams" />
|
||||||
<div class="grid grid-flow-col gap-[1.5vw] mt-[3%]">
|
<div class="relative w-[75vw] h-[50vh] mt-[3%]">
|
||||||
{subteams.map((subteam)=>(
|
<div id="carousel" class="absolute w-full h-full flex justify-center">
|
||||||
<Subteam title={subteam.title} list={subteam.list} />
|
{
|
||||||
))}
|
duplicatedSubteams.map((subteam, index) => {
|
||||||
|
let distance = index - centerIndex;
|
||||||
|
// wrap
|
||||||
|
if (distance > duplicatedSubteams.length / 2) {
|
||||||
|
distance -= duplicatedSubteams.length;
|
||||||
|
} else if (distance < -duplicatedSubteams.length / 2) {
|
||||||
|
distance += duplicatedSubteams.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class="carousel-item absolute transition-all duration-500"
|
||||||
|
style={{
|
||||||
|
transform: `translateX(${distance * 12}vw) scale(${
|
||||||
|
Math.abs(distance) === 0
|
||||||
|
? 1.2
|
||||||
|
: Math.abs(distance) === 1
|
||||||
|
? 1.0
|
||||||
|
: 0.8
|
||||||
|
})`,
|
||||||
|
opacity: Math.abs(distance) <= 2 ? 1 : 0,
|
||||||
|
zIndex:
|
||||||
|
Math.abs(distance) === 0
|
||||||
|
? 30
|
||||||
|
: Math.abs(distance) === 1
|
||||||
|
? 20
|
||||||
|
: 10,
|
||||||
|
width: "20vw",
|
||||||
|
}}
|
||||||
|
data-index={index}
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<div class="relative w-full h-full backdrop-blur-md overflow-hidden rounded-[2vw]">
|
||||||
|
<div class="px-[10%] flex flex-col justify-center items-center w-[20vw] h-[38vh] bg-gradient-to-b from-ieee-blue-100/25 to-ieee-black backdrop-blur rounded-[2vw] border-white/40 border-[0.1vw]">
|
||||||
|
<p class="text-[1.5vw] mb-[10%] font-semibold pt-[10%]">
|
||||||
|
{subteam.title}
|
||||||
|
</p>
|
||||||
|
<ul class="text-[1vw] font-light">
|
||||||
|
{subteam.list.map(
|
||||||
|
(item: string) => (
|
||||||
|
<li>• {item}</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="-top-[10%] left-1/2 -translate-x-1/2 w-fit p-[5%] shadow-ieee-blue-300 text-[3.2vw] bg-gradient-to-b from-ieee-blue-100 to-ieee-blue-300 rounded-full absolute">
|
||||||
|
{subteam.title === "Mechanical" && (
|
||||||
|
<FaGear />
|
||||||
|
)}
|
||||||
|
{subteam.title === "Electrical" && (
|
||||||
|
<FaMicrochip />
|
||||||
|
)}
|
||||||
|
{subteam.title === "AI" && (
|
||||||
|
<LuBrainCircuit />
|
||||||
|
)}
|
||||||
|
{subteam.title === "Embedded" && <FaCode />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
id="prevBtn"
|
||||||
|
class="absolute left-[-3vw] top-[calc(50%-1.5vw)] transform -translate-y-1/2 text-[3vw] text-white hover:text-white/70 duration-300 z-20 bg-black/30 hover:bg-black/50 p-2 rounded-full backdrop-blur-sm"
|
||||||
|
aria-label="Previous card"
|
||||||
|
>
|
||||||
|
<IoIosArrowBack />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="nextBtn"
|
||||||
|
class="absolute right-[-3vw] top-[calc(50%-1.5vw)] transform -translate-y-1/2 text-[3vw] text-white hover:text-white/70 duration-300 z-20 bg-black/30 hover:bg-black/50 p-2 rounded-full backdrop-blur-sm"
|
||||||
|
aria-label="Next card"
|
||||||
|
>
|
||||||
|
<IoIosArrowForward />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.carousel-item {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item[data-loaded="true"] {
|
||||||
|
transition:
|
||||||
|
transform 500ms,
|
||||||
|
opacity 200ms;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const items = document.querySelectorAll(".carousel-item");
|
||||||
|
const totalItems = items.length;
|
||||||
|
const singleSetLength = totalItems / 3; // length of one set of cards
|
||||||
|
let currentIndex = singleSetLength;
|
||||||
|
const prevBtn = document.getElementById("prevBtn");
|
||||||
|
const nextBtn = document.getElementById("nextBtn");
|
||||||
|
let autoAdvanceTimer: ReturnType<typeof setInterval>;
|
||||||
|
let isAnimating = false;
|
||||||
|
let isTransitioning = false;
|
||||||
|
|
||||||
|
function startAutoAdvance() {
|
||||||
|
if (autoAdvanceTimer) {
|
||||||
|
clearInterval(autoAdvanceTimer);
|
||||||
|
}
|
||||||
|
autoAdvanceTimer = setInterval(() => {
|
||||||
|
if (!isAnimating && !isTransitioning) {
|
||||||
|
updateCards(currentIndex + 1);
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
items.forEach((item) => {
|
||||||
|
item.setAttribute("data-loaded", "true");
|
||||||
|
});
|
||||||
|
startAutoAdvance();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
function updateCards(newIndex: number): void {
|
||||||
|
if (isAnimating || isTransitioning) return;
|
||||||
|
isAnimating = true;
|
||||||
|
isTransitioning = true;
|
||||||
|
|
||||||
|
// direction of movement
|
||||||
|
const direction = newIndex > currentIndex ? 1 : -1;
|
||||||
|
|
||||||
|
items.forEach((item, index) => {
|
||||||
|
const el = item as HTMLElement;
|
||||||
|
let distance = index - newIndex;
|
||||||
|
|
||||||
|
// wrap
|
||||||
|
if (distance > singleSetLength) {
|
||||||
|
distance -= totalItems;
|
||||||
|
} else if (distance < -singleSetLength) {
|
||||||
|
distance += totalItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scale =
|
||||||
|
Math.abs(distance) === 0
|
||||||
|
? 1.2
|
||||||
|
: Math.abs(distance) === 1
|
||||||
|
? 1
|
||||||
|
: Math.abs(distance) === 2
|
||||||
|
? 0.8
|
||||||
|
: 0.6; // smaller scale for hidden cards (to transition)
|
||||||
|
|
||||||
|
// show only 5 cards at once (2 on each side)
|
||||||
|
el.style.transform = `translateX(${distance * 12}vw) scale(${scale})`;
|
||||||
|
el.style.opacity = Math.abs(distance) <= 2 ? "1" : "0";
|
||||||
|
el.style.zIndex =
|
||||||
|
Math.abs(distance) === 0
|
||||||
|
? "30"
|
||||||
|
: Math.abs(distance) === 1
|
||||||
|
? "20"
|
||||||
|
: "10";
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update index with wrapping
|
||||||
|
if (newIndex >= totalItems) {
|
||||||
|
newIndex = 0;
|
||||||
|
} else if (newIndex < 0) {
|
||||||
|
newIndex = totalItems - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex = newIndex;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
isAnimating = false;
|
||||||
|
// small delay before allowing next transition
|
||||||
|
setTimeout(() => {
|
||||||
|
isTransitioning = false;
|
||||||
|
}, 50);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// button clicks
|
||||||
|
prevBtn?.addEventListener("click", () => {
|
||||||
|
if (!isAnimating && !isTransitioning) {
|
||||||
|
updateCards(currentIndex - 1);
|
||||||
|
startAutoAdvance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
nextBtn?.addEventListener("click", () => {
|
||||||
|
if (!isAnimating && !isTransitioning) {
|
||||||
|
updateCards(currentIndex + 1);
|
||||||
|
startAutoAdvance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// click handler for cards
|
||||||
|
items.forEach((item, index) => {
|
||||||
|
item.addEventListener("click", () => {
|
||||||
|
if (isAnimating || isTransitioning) return;
|
||||||
|
|
||||||
|
const distance = index - currentIndex;
|
||||||
|
|
||||||
|
// visual position of the clicked card
|
||||||
|
let visualDistance = distance;
|
||||||
|
if (distance > totalItems / 2) {
|
||||||
|
visualDistance -= totalItems;
|
||||||
|
} else if (distance < -totalItems / 2) {
|
||||||
|
visualDistance += totalItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only allow clicking on visible cards that aren't in the center
|
||||||
|
if (Math.abs(visualDistance) <= 2 && visualDistance !== 0) {
|
||||||
|
let targetIndex = currentIndex + visualDistance;
|
||||||
|
|
||||||
|
if (targetIndex >= totalItems) {
|
||||||
|
targetIndex = targetIndex % totalItems;
|
||||||
|
} else if (targetIndex < 0) {
|
||||||
|
targetIndex = totalItems + (targetIndex % totalItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCards(targetIndex);
|
||||||
|
startAutoAdvance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"Robocup": {
|
"Robocup": {
|
||||||
"description": "Participate in the Robocup competition.",
|
"description": "Participate in the Robocup competition.",
|
||||||
"image": "/robocup.png",
|
"image": "/robocup.webp",
|
||||||
"url": "/robocup"
|
"url": "/robocup"
|
||||||
},
|
},
|
||||||
"Signal Processing": {
|
"Signal Processing": {
|
||||||
"description": "Explore the field of signal processing.",
|
"description": "Explore the field of signal processing.",
|
||||||
"image": "/signal.png",
|
"image": "/signal.webp",
|
||||||
"url": "/signal"
|
"url": "/signal"
|
||||||
},
|
},
|
||||||
"Supercomputing": {
|
"Supercomputing": {
|
||||||
"description": "Explore the field of supercomputing.",
|
"description": "Explore the field of supercomputing.",
|
||||||
"image": "/supercomp.png",
|
"image": "/supercomp.webp",
|
||||||
"url": "https://supercomputing-club.sdsc.edu/"
|
"url": "https://supercomputing-club.sdsc.edu/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"text": "PROJECTS",
|
"text": "PROJECTS",
|
||||||
"image": "/project.png",
|
"image": "/project.webp",
|
||||||
"link": "/projects",
|
"link": "/projects",
|
||||||
"delay": "100"
|
"delay": "100"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "EVENTS",
|
"text": "EVENTS",
|
||||||
"image": "/halloween.png",
|
"image": "/halloween.webp",
|
||||||
"link": "/events",
|
"link": "/events",
|
||||||
"delay": "300"
|
"delay": "300"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "H.A.R.D. HACK",
|
"text": "H.A.R.D. HACK",
|
||||||
"image": "/hardhack.png",
|
"image": "/hardhack.webp",
|
||||||
"link": "https://hardhack.dev/",
|
"link": "https://hardhack.dev/",
|
||||||
"delay": "500"
|
"delay": "500"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
{
|
{
|
||||||
"name": "Mustahsin Zarif",
|
"name": "Mustahsin Zarif",
|
||||||
"position": "Chair",
|
"position": "Chair",
|
||||||
"picture": "/officers/zarif.png",
|
"picture": "/officers/zarif.webp",
|
||||||
"email": "mmzarif@ucsd.edu",
|
"email": "mmzarif@ucsd.edu",
|
||||||
"type": ["Executives"]
|
"type": ["Executives"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Stephanie Xu",
|
"name": "Stephanie Xu",
|
||||||
"position": "Vice Chair Internal",
|
"position": "Vice Chair Internal",
|
||||||
"picture": "/officers/steph.jpg",
|
"picture": "/officers/steph.webp",
|
||||||
"email": "sxxu@ucsd.edu",
|
"email": "sxxu@ucsd.edu",
|
||||||
"type": ["Executives", "Internal"]
|
"type": ["Executives", "Internal"]
|
||||||
},
|
},
|
||||||
|
@ -23,77 +23,77 @@
|
||||||
{
|
{
|
||||||
"name": "Rohil Kadekar",
|
"name": "Rohil Kadekar",
|
||||||
"position": "Vice Chair Projects",
|
"position": "Vice Chair Projects",
|
||||||
"picture": "/officers/rohil.jpg",
|
"picture": "/officers/rohil.webp",
|
||||||
"email": "rkadekar@ucsd.edu",
|
"email": "rkadekar@ucsd.edu",
|
||||||
"type": ["Executives", "Projects"]
|
"type": ["Executives", "Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Shipra Gudekar",
|
"name": "Shipra Gudekar",
|
||||||
"position": "Vice Chair Events",
|
"position": "Vice Chair Events",
|
||||||
"picture": "/officers/shipra.jpg",
|
"picture": "/officers/shipra.webp",
|
||||||
"email": "sgudekar@ucsd.edu",
|
"email": "sgudekar@ucsd.edu",
|
||||||
"type": ["Executives", "Events"]
|
"type": ["Executives", "Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Lisa Liu",
|
"name": "Lisa Liu",
|
||||||
"position": "Vice Chair Finance",
|
"position": "Vice Chair Finance",
|
||||||
"picture": "/officers/lisa.jpg",
|
"picture": "/officers/lisa.webp",
|
||||||
"email": "lil043@ucsd.edu",
|
"email": "lil043@ucsd.edu",
|
||||||
"type": ["Executives"]
|
"type": ["Executives"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Charles Nguyen",
|
"name": "Charles Nguyen",
|
||||||
"position": "Webmaster",
|
"position": "Webmaster",
|
||||||
"picture": "/officers/charles.jpg",
|
"picture": "/officers/charles.webp",
|
||||||
"email": "cmn010@ucsd.edu",
|
"email": "cmn010@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Shing Hung",
|
"name": "Shing Hung",
|
||||||
"position": "Webmaster",
|
"position": "Webmaster",
|
||||||
"picture": "/officers/shing.jpg",
|
"picture": "/officers/shing.webp",
|
||||||
"email": "s1hung@ucsd.edu",
|
"email": "s1hung@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Andy Smithwick",
|
"name": "Andy Smithwick",
|
||||||
"position": "Webmaster",
|
"position": "Webmaster",
|
||||||
"picture": "/officers/andy.jpg",
|
"picture": "/officers/andy.webp",
|
||||||
"email": "asmithwick@ucsd.edu",
|
"email": "asmithwick@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Stella Ji",
|
"name": "Stella Ji",
|
||||||
"position": "Marketing Chair",
|
"position": "Marketing Chair",
|
||||||
"picture": "/officers/stella.jpg",
|
"picture": "/officers/stella.webp",
|
||||||
"email": "seji@ucsd.edu",
|
"email": "seji@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Lauren Vo",
|
"name": "Lauren Vo",
|
||||||
"position": "Marketing Chair",
|
"position": "Marketing Chair",
|
||||||
"picture": "/officers/lauren.jpg",
|
"picture": "/officers/lauren.webp",
|
||||||
"email": "lavo@ucsd.edu",
|
"email": "lavo@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Wan-Rong (Emma) Leung",
|
"name": "Emma Leung",
|
||||||
"position": "Design Chair",
|
"position": "Design Chair",
|
||||||
"picture": "/officers/emma.jpg",
|
"picture": "/officers/emma.webp",
|
||||||
"email": "waleung@ucsd.edu",
|
"email": "waleung@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Christine Uy",
|
"name": "Christine Uy",
|
||||||
"position": "Design Chair",
|
"position": "Design Chair",
|
||||||
"picture": "/officers/christine.jpg",
|
"picture": "/officers/christine.webp",
|
||||||
"email": "c1uy@ucsd.edu",
|
"email": "c1uy@ucsd.edu",
|
||||||
"type": ["Internal"]
|
"type": ["Internal"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Erik Duarte",
|
"name": "Erik Duarte",
|
||||||
"position": "Events Coordinator",
|
"position": "Events Coordinator",
|
||||||
"picture": "/officers/erik.jpg",
|
"picture": "/officers/erik.webp",
|
||||||
"email": "Erduarte@ucsd.edu",
|
"email": "Erduarte@ucsd.edu",
|
||||||
"type": ["Executives", "Events"]
|
"type": ["Executives", "Events"]
|
||||||
},
|
},
|
||||||
|
@ -107,56 +107,56 @@
|
||||||
{
|
{
|
||||||
"name": "Rafaella Gomes",
|
"name": "Rafaella Gomes",
|
||||||
"position": "Project Space Chair",
|
"position": "Project Space Chair",
|
||||||
"picture": "/officers/rafaella.jpg",
|
"picture": "/officers/rafaella.webp",
|
||||||
"email": "ragomes@ucsd.edu",
|
"email": "ragomes@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Terri Tai",
|
"name": "Terri Tai",
|
||||||
"position": "Robocup Soccer Chair",
|
"position": "Robocup Soccer Chair",
|
||||||
"picture": "/officers/terri.jpg",
|
"picture": "/officers/terri.webp",
|
||||||
"email": "y2tai@ucsd.edu",
|
"email": "y2tai@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Raymond Rada",
|
"name": "Raymond Rada",
|
||||||
"position": "Robocup Soccer Chair",
|
"position": "Robocup Soccer Chair",
|
||||||
"picture": "/officers/raymond.jpg",
|
"picture": "/officers/raymond.webp",
|
||||||
"email": "rrada@ucsd.edu",
|
"email": "rrada@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Philip Pincencia",
|
"name": "Philip Pincencia",
|
||||||
"position": "Signal Processing Chair",
|
"position": "Signal Processing Chair",
|
||||||
"picture": "/officers/philip.jpg",
|
"picture": "/officers/philip.webp",
|
||||||
"email": "ppincencia@ucsd.edu",
|
"email": "ppincencia@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Akhil Ram Shankar",
|
"name": "Akhil Ram Shankar",
|
||||||
"position": "Quarterly Projects Chair",
|
"position": "Quarterly Projects Chair",
|
||||||
"picture": "/officers/akhil.jpg",
|
"picture": "/officers/akhil.webp",
|
||||||
"email": "aramshankar@ucsd.edu",
|
"email": "aramshankar@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Jonathan Zhou",
|
"name": "Jonathan Zhou",
|
||||||
"position": "Quarterly Projects Chair",
|
"position": "Quarterly Projects Chair",
|
||||||
"picture": "/officers/jonathan.jpg",
|
"picture": "/officers/jonathan.webp",
|
||||||
"email": "jtzhou@ucsd.edu",
|
"email": "jtzhou@ucsd.edu",
|
||||||
"type": ["Projects"]
|
"type": ["Projects"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Ashlee Young",
|
"name": "Ashlee Young",
|
||||||
"position": "Professional Chair",
|
"position": "Professional Chair",
|
||||||
"picture": "/officers/ashlee.jpg",
|
"picture": "/officers/ashlee.webp",
|
||||||
"email": "asy001@ucsd.edu",
|
"email": "asy001@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Allie Dinh",
|
"name": "Allie Dinh",
|
||||||
"position": "Professional Chair",
|
"position": "Professional Chair",
|
||||||
"picture": "/officers/allie.jpg",
|
"picture": "/officers/allie.webp",
|
||||||
"email": "ald012@ucsd.edu",
|
"email": "ald012@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
|
@ -170,35 +170,35 @@
|
||||||
{
|
{
|
||||||
"name": "Pranav Mehta",
|
"name": "Pranav Mehta",
|
||||||
"position": "Technical Chair",
|
"position": "Technical Chair",
|
||||||
"picture": "/officers/pranav.jpg",
|
"picture": "/officers/pranav.webp",
|
||||||
"email": "p3mehta@ucsd.edu",
|
"email": "p3mehta@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Ridhi Srikanth",
|
"name": "Ridhi Srikanth",
|
||||||
"position": "Technical Chair",
|
"position": "Technical Chair",
|
||||||
"picture": "/officers/ridhi.jpg",
|
"picture": "/officers/ridhi.webp",
|
||||||
"email": "rsrikanth@ucsd.edu",
|
"email": "rsrikanth@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Anika Agarwal",
|
"name": "Anika Agarwal",
|
||||||
"position": "Outreach Chair",
|
"position": "Outreach Chair",
|
||||||
"picture": "/officers/anika.jpg",
|
"picture": "/officers/anika.webp",
|
||||||
"email": "ana012@ucsd.edu",
|
"email": "ana012@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Anupama Nambiar",
|
"name": "Anupama Nambiar",
|
||||||
"position": "Social Chair",
|
"position": "Social Chair",
|
||||||
"picture": "/officers/anu.jpg",
|
"picture": "/officers/anu.webp",
|
||||||
"email": "annambiar@ucsd.edu",
|
"email": "annambiar@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Dhruv Roy Choudhary",
|
"name": "Dhruv Roy Choudhary",
|
||||||
"position": "Social Chair",
|
"position": "Social Chair",
|
||||||
"picture": "/officers/dhruv.jpg",
|
"picture": "/officers/dhruv.webp",
|
||||||
"email": "dchoudhary@ucsd.edu",
|
"email": "dchoudhary@ucsd.edu",
|
||||||
"type": ["Events"]
|
"type": ["Events"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/robocup.png",
|
"image": "/robocup.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "2"
|
"col": "2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/signal.png",
|
"image": "/signal.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "4"
|
"col": "4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/robocup.png",
|
"image": "/robocup.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "3"
|
"col": "3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/signal.png",
|
"image": "/signal.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "3"
|
"col": "3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/signal.png",
|
"image": "/signal.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "2"
|
"col": "2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/robocup.png",
|
"image": "/robocup.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "2"
|
"col": "2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Retro Gaming Console",
|
"title": "Retro Gaming Console",
|
||||||
"image": "/robocup.png",
|
"image": "/robocup.webp",
|
||||||
"link": "/",
|
"link": "/",
|
||||||
"col": "2"
|
"col": "2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,32 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"title": "Mechanical",
|
"title": "Mechanical",
|
||||||
"list": ["Design the Mechanisms and Structure of the Robot",
|
"list": [
|
||||||
|
"Design the Mechanisms and Structure of the Robot",
|
||||||
"Fabricate and assemble robot design",
|
"Fabricate and assemble robot design",
|
||||||
"Integrate electronics and other hardware"]
|
"Integrate electronics and other hardware"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Electrical",
|
"title": "Electrical",
|
||||||
"list": ["Design circuits to power and control robot subsystems",
|
"list": [
|
||||||
"Work with mechanical team to assemble electronics in the robots"]
|
"Design circuits to power and control robot subsystems",
|
||||||
|
"Work with mechanical team to assemble electronics in the robots"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Embedded",
|
"title": "Embedded",
|
||||||
"list": ["Communicate between software and hardware",
|
"list": [
|
||||||
|
"Communicate between software and hardware",
|
||||||
"Provide low level software interface and API",
|
"Provide low level software interface and API",
|
||||||
"Handle and sample data using math/physics knowledge"
|
"Handle and sample data using math/physics knowledge"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "AI",
|
||||||
|
"list": [
|
||||||
|
"Design decision making algorithms using behavioral trees",
|
||||||
|
"Conduct testing with simulation"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Before Width: | Height: | Size: 21 KiB |
BIN
src/images/about.webp
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 5.1 MiB |
BIN
src/images/about2.webp
Normal file
After Width: | Height: | Size: 4.7 MiB |