From c352bdbee565df628a11f5105e3dfab5e58fbcec Mon Sep 17 00:00:00 2001 From: Sam Der Date: Tue, 24 Oct 2023 13:25:59 -0700 Subject: [PATCH 1/6] fix: change faq heading to h3 --- apps/site/src/views/Home/sections/FAQ/FAQAccordion.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/site/src/views/Home/sections/FAQ/FAQAccordion.tsx b/apps/site/src/views/Home/sections/FAQ/FAQAccordion.tsx index 2c3a7aca..28f4dee6 100644 --- a/apps/site/src/views/Home/sections/FAQ/FAQAccordion.tsx +++ b/apps/site/src/views/Home/sections/FAQ/FAQAccordion.tsx @@ -14,13 +14,13 @@ interface FAQAccordion { export default function FAQAccordion({ faq }: FAQAccordion) { return ( - {faq.map(({ _key, question, answer }, index) => ( + {faq.map(({ _key, question, answer }) => ( - + {question} {answer} From 90aafbb81b2cf097ec325e2d15586f5975be9a33 Mon Sep 17 00:00:00 2001 From: Alexander Liu Date: Sat, 28 Oct 2023 15:36:38 -0700 Subject: [PATCH 2/6] feature/sponsors (#97) * feat: sponsors schema * feat: sponsor schema tier * feat: sponsor section * fix: sponsors heading h2 * fix: extraneous left padding on mobile clipboard * fix: remove duplicate padding --- apps/sanity/sanity.config.ts | 13 +++- apps/sanity/schemas/index.ts | 3 +- apps/sanity/schemas/sponsors.ts | 61 +++++++++++++++++ apps/site/package.json | 1 + apps/site/src/lib/sanity/types.ts | 27 +++++++- apps/site/src/views/Home/Home.tsx | 2 + .../sections/Sponsors/Sponsors.module.scss | 68 +++++++++++++++++++ .../views/Home/sections/Sponsors/Sponsors.tsx | 35 +++++++--- .../src/views/Home/sections/Sponsors/clip.svg | 4 ++ .../Home/sections/Sponsors/getSponsors.ts | 21 ++++++ pnpm-lock.yaml | 21 +++++- 11 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 apps/sanity/schemas/sponsors.ts create mode 100644 apps/site/src/views/Home/sections/Sponsors/Sponsors.module.scss create mode 100644 apps/site/src/views/Home/sections/Sponsors/clip.svg create mode 100644 apps/site/src/views/Home/sections/Sponsors/getSponsors.ts diff --git a/apps/sanity/sanity.config.ts b/apps/sanity/sanity.config.ts index e7253603..599eda42 100644 --- a/apps/sanity/sanity.config.ts +++ b/apps/sanity/sanity.config.ts @@ -4,7 +4,7 @@ import { visionTool } from "@sanity/vision"; import { colorInput } from "@sanity/color-input"; import { media } from "sanity-plugin-media"; import { schemaTypes } from "./schemas"; -import { BadgeHelp } from "lucide-react"; +import { HeartHandshake, BadgeHelp } from "lucide-react"; export default defineConfig({ name: "default", @@ -19,6 +19,15 @@ export default defineConfig({ S.list() .title("Content") .items([ + S.listItem() + .title("Sponsors") + .icon(HeartHandshake) + .child( + S.document() + .schemaType("sponsors") + .documentId("sponsors") + .title("Sponsors") + ), S.listItem() .title("FAQs") .icon(BadgeHelp) @@ -27,7 +36,7 @@ export default defineConfig({ ), S.divider(), ...S.documentTypeListItems().filter( - (listItem) => !["faqs"].includes(listItem.getId()!) + (listItem) => !["faqs", "sponsors"].includes(listItem.getId()!) ), ]), }), diff --git a/apps/sanity/schemas/index.ts b/apps/sanity/schemas/index.ts index c4344632..78338c4d 100644 --- a/apps/sanity/schemas/index.ts +++ b/apps/sanity/schemas/index.ts @@ -1,5 +1,6 @@ import faqs from "./faqs"; import event from "./event"; import resource from "./resource"; +import sponsors from "./sponsors"; -export const schemaTypes = [faqs, event, resource]; +export const schemaTypes = [faqs, event, resource, sponsors]; diff --git a/apps/sanity/schemas/sponsors.ts b/apps/sanity/schemas/sponsors.ts new file mode 100644 index 00000000..71bf3447 --- /dev/null +++ b/apps/sanity/schemas/sponsors.ts @@ -0,0 +1,61 @@ +import { defineType, defineField, defineArrayMember } from "sanity"; +import { HeartHandshake } from "lucide-react"; + +export default defineType({ + name: "sponsors", + title: "Sponsors", + icon: HeartHandshake, + type: "document", + fields: [ + defineField({ + name: "sponsors", + title: "Sponsors", + type: "array", + of: [ + defineArrayMember({ + type: "object", + name: "sponsor", + fields: [ + defineField({ + name: "name", + title: "Name", + type: "string", + validation: (Rule) => Rule.required(), + }), + defineField({ + name: "url", + title: "URL", + type: "url", + }), + defineField({ + name: "tier", + title: "Tier", + type: "string", + options: { + list: [ + { + title: "Bronze", + value: "bronze", + }, + { + title: "Silver", + value: "silver", + }, + ], + layout: "radio", + direction: "vertical", + }, + validation: (Rule) => Rule.required(), + }), + defineField({ + name: "logo", + title: "Logo", + type: "image", + validation: (Rule) => Rule.required(), + }), + ], + }), + ], + }), + ], +}); diff --git a/apps/site/package.json b/apps/site/package.json index 29c1cf25..e0dd6f2f 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@portabletext/react": "^3.0.7", + "@sanity/image-url": "^1.0.2", "@types/node": "20.4.9", "@types/react": "18.2.20", "@types/react-dom": "^18.2.0", diff --git a/apps/site/src/lib/sanity/types.ts b/apps/site/src/lib/sanity/types.ts index 0b3c6ee8..69b15128 100644 --- a/apps/site/src/lib/sanity/types.ts +++ b/apps/site/src/lib/sanity/types.ts @@ -5,4 +5,29 @@ export const SanityDocument = z.object({ _createdAt: z.string().datetime(), _updatedAt: z.string().datetime(), _rev: z.string(), -}); \ No newline at end of file +}); + +export const SanityReference = z.object({ + _type: z.literal("reference"), + _ref: z.string(), +}); +export const SanityImageCrop = z.object({ + _type: z.literal("sanity.imageCrop"), + top: z.number(), + bottom: z.number(), + left: z.number(), + right: z.number(), +}); +export const SanityImageHotspot = z.object({ + _type: z.literal("sanity.imageHotspot"), + x: z.number(), + y: z.number(), + height: z.number(), + width: z.number(), +}); +export const SanityImageReference = z.object({ + _type: z.literal("image"), + asset: SanityReference, + crop: SanityImageCrop.optional(), + hotspot: SanityImageHotspot.optional(), +}); diff --git a/apps/site/src/views/Home/Home.tsx b/apps/site/src/views/Home/Home.tsx index c698ff45..ea164ae1 100644 --- a/apps/site/src/views/Home/Home.tsx +++ b/apps/site/src/views/Home/Home.tsx @@ -1,6 +1,7 @@ import Landing from "./sections/Landing/Landing"; import Intro from "./sections/Intro/Intro"; import Mentor from "./sections/Mentor/Mentor"; +import Sponsors from "./sections/Sponsors/Sponsors"; import FAQ from "./sections/FAQ/FAQ"; import StickerLayout from "./components/StickerLayout/StickerLayout"; @@ -15,6 +16,7 @@ function Home() { + diff --git a/apps/site/src/views/Home/sections/Sponsors/Sponsors.module.scss b/apps/site/src/views/Home/sections/Sponsors/Sponsors.module.scss new file mode 100644 index 00000000..51912663 --- /dev/null +++ b/apps/site/src/views/Home/sections/Sponsors/Sponsors.module.scss @@ -0,0 +1,68 @@ +@use "zothacks-theme" as theme; +@use "bootstrap-utils" as utils; + +.container { + padding-top: 6rem; + padding-bottom: 6rem; +} + +.title { + text-align: center; +} + +.clipboard { + position: relative; + padding: 64px 32px 48px 32px; + min-height: 512px; + width: 80%; + margin: 0 auto; + border: 20px solid #aa703c; + border-radius: 100px; + background: #ffffff; + display: flex; + flex-direction: column; + align-items: stretch; + + @include utils.media-breakpoint-up(sm) { + padding: 32px 32px 48px 32px; + } +} + +.clip { + height: 192px; + position: absolute; + left: 50%; + transform: translateX(-50%) rotate(90deg); + top: -105px; + + @include utils.media-breakpoint-up(sm) { + height: 256px; + top: 50%; + transform: translateY(-50%); + left: -85px; + } +} + +.logos { + flex-grow: 1; + display: grid; + align-items: center; + align-content: center; + justify-content: center; + grid-template-columns: repeat(auto-fill, 192px); + gap: 32px; + + @include utils.media-breakpoint-up(sm) { + padding-left: 24px; + grid-template-columns: repeat(auto-fill, 256px); + } + + @include utils.media-breakpoint-up(md) { + grid-template-columns: repeat(auto-fill, 384px); + padding-left: 48px; + } +} + +.logo { + width: 100%; +} diff --git a/apps/site/src/views/Home/sections/Sponsors/Sponsors.tsx b/apps/site/src/views/Home/sections/Sponsors/Sponsors.tsx index 6ab53030..68030354 100644 --- a/apps/site/src/views/Home/sections/Sponsors/Sponsors.tsx +++ b/apps/site/src/views/Home/sections/Sponsors/Sponsors.tsx @@ -1,13 +1,32 @@ -"use client"; +/* eslint-disable @next/next/no-img-element */ +import { getSponsors } from "./getSponsors"; +import styles from "./Sponsors.module.scss"; +import { client } from "@/lib/sanity/client"; +import imageUrlBuilder from "@sanity/image-url"; +import clip from "./clip.svg"; -import Container from "react-bootstrap/Container"; +const builder = imageUrlBuilder(client); + +export default async function Sponsors() { + const sponsors = await getSponsors(); -function Sponsors() { return ( - -

Sponsors

-
+
+
+ +

Sponsors

+
+ {sponsors.sponsors.map(({ _key, name, url, logo }) => ( + + {name + + ))} +
+
+
); } - -export default Sponsors; diff --git a/apps/site/src/views/Home/sections/Sponsors/clip.svg b/apps/site/src/views/Home/sections/Sponsors/clip.svg new file mode 100644 index 00000000..7216f455 --- /dev/null +++ b/apps/site/src/views/Home/sections/Sponsors/clip.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/apps/site/src/views/Home/sections/Sponsors/getSponsors.ts b/apps/site/src/views/Home/sections/Sponsors/getSponsors.ts new file mode 100644 index 00000000..d9bc4241 --- /dev/null +++ b/apps/site/src/views/Home/sections/Sponsors/getSponsors.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; +import { cache } from "react"; +import { client } from "@/lib/sanity/client"; +import { SanityDocument, SanityImageReference } from "@/lib/sanity/types"; + +const Sponsors = SanityDocument.extend({ + sponsors: z.array( + z.object({ + _type: z.literal("sponsor"), + _key: z.string(), + name: z.string(), + url: z.string().url().optional(), + tier: z.union([z.literal("bronze"), z.literal("silver")]), + logo: SanityImageReference, + }), + ), +}); + +export const getSponsors = cache(async () => { + return Sponsors.parse(await client.fetch("*[_id == 'sponsors'][0]")); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f62f99e8..cf2f313d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,6 +78,9 @@ importers: '@portabletext/react': specifier: ^3.0.7 version: 3.0.7(react@18.2.0) + '@sanity/image-url': + specifier: ^1.0.2 + version: 1.0.2 '@types/node': specifier: 20.4.9 version: 20.4.9 @@ -1498,6 +1501,20 @@ packages: '@lezer/common': 1.0.3 dev: false + /@codemirror/autocomplete@6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4): + resolution: {integrity: sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/common': ^1.0.0 + dependencies: + '@codemirror/language': 6.8.0 + '@codemirror/state': 6.2.1 + '@codemirror/view': 6.16.0 + '@lezer/common': 1.0.4 + dev: false + /@codemirror/autocomplete@6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4): resolution: {integrity: sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==} peerDependencies: @@ -2780,7 +2797,7 @@ packages: react: ^18 styled-components: ^5.2 dependencies: - '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4) + '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4) '@codemirror/commands': 6.2.4 '@codemirror/lang-javascript': 6.1.9 '@codemirror/language': 6.8.0 @@ -3282,7 +3299,7 @@ packages: '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' dependencies: - '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4) + '@codemirror/autocomplete': 6.9.0(@codemirror/language@6.8.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4) '@codemirror/commands': 6.2.4 '@codemirror/language': 6.8.0 '@codemirror/lint': 6.4.0 From 0bb0d9576232c37c2a6f427547bf6a62a09ee7e5 Mon Sep 17 00:00:00 2001 From: Alexander Liu Date: Sun, 29 Oct 2023 09:13:42 -0700 Subject: [PATCH 3/6] feat: change event description to portable text field --- apps/sanity/schemas/event.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/sanity/schemas/event.ts b/apps/sanity/schemas/event.ts index c535fabc..0245bc39 100644 --- a/apps/sanity/schemas/event.ts +++ b/apps/sanity/schemas/event.ts @@ -32,8 +32,16 @@ export default defineType({ }), defineField({ name: "description", - title: "description", - type: "text" - }) + title: "Description", + type: "array", + of: [ + { + type: "block", + styles: [{ title: "Normal", value: "normal" }], + lists: [], + }, + ], + validation: (Rule) => Rule.required(), + }), ], }); From 2df99f997c7476b833ac5595e2eb861a0de31d3e Mon Sep 17 00:00:00 2001 From: Sam Der Date: Sun, 29 Oct 2023 13:49:41 -0700 Subject: [PATCH 4/6] Set up sample clipboard (#95) * feat: Schedule Page component structure feat: component organiztion on schedule page * feature: create clipboard schedule * feat: draft clipboard * fix: build error * fix: heading sizes and h1 title * fix: Bootstrap vars, set up Accordion item map * fix: remove unused files * fix: responsive margins, accessibility * fix: simplify accordion header layout --------- Co-authored-by: Tyler Yu Co-authored-by: Albert Wang --- .../src/app/resources/{#page.tsx => page.tsx} | 0 .../src/app/schedule/{#page.tsx => page.tsx} | 0 apps/site/src/assets/icons/accordion-btn.svg | 21 +++++++ apps/site/src/assets/images/clip.svg | 22 +++++++ apps/site/src/lib/styles/_zothacks-theme.scss | 1 + apps/site/src/lib/styles/globals.scss | 19 ++++++ .../views/Home/sections/FAQ/FAQ.module.scss | 7 --- .../src/views/Schedule/Schedule.module.scss | 21 +++++++ apps/site/src/views/Schedule/Schedule.tsx | 21 ++++++- .../ClipboardSchedule.module.scss | 36 +++++++++++ .../ClipboardSchedule/ClipboardSchedule.tsx | 61 +++++++++++++++++++ 11 files changed, 200 insertions(+), 9 deletions(-) rename apps/site/src/app/resources/{#page.tsx => page.tsx} (100%) rename apps/site/src/app/schedule/{#page.tsx => page.tsx} (100%) create mode 100644 apps/site/src/assets/icons/accordion-btn.svg create mode 100644 apps/site/src/assets/images/clip.svg create mode 100644 apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.module.scss create mode 100644 apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.tsx diff --git a/apps/site/src/app/resources/#page.tsx b/apps/site/src/app/resources/page.tsx similarity index 100% rename from apps/site/src/app/resources/#page.tsx rename to apps/site/src/app/resources/page.tsx diff --git a/apps/site/src/app/schedule/#page.tsx b/apps/site/src/app/schedule/page.tsx similarity index 100% rename from apps/site/src/app/schedule/#page.tsx rename to apps/site/src/app/schedule/page.tsx diff --git a/apps/site/src/assets/icons/accordion-btn.svg b/apps/site/src/assets/icons/accordion-btn.svg new file mode 100644 index 00000000..0bef7079 --- /dev/null +++ b/apps/site/src/assets/icons/accordion-btn.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/clip.svg b/apps/site/src/assets/images/clip.svg new file mode 100644 index 00000000..4cd185d2 --- /dev/null +++ b/apps/site/src/assets/images/clip.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/lib/styles/_zothacks-theme.scss b/apps/site/src/lib/styles/_zothacks-theme.scss index 9ec26c33..bbc59f3d 100644 --- a/apps/site/src/lib/styles/_zothacks-theme.scss +++ b/apps/site/src/lib/styles/_zothacks-theme.scss @@ -16,3 +16,4 @@ $light-blue: #81deeb; $blue: #3902fd; $purple: #6600b6; $navbar-red: #ff0000; +$brown: #aa703c; diff --git a/apps/site/src/lib/styles/globals.scss b/apps/site/src/lib/styles/globals.scss index 1d73ccee..345a64c4 100644 --- a/apps/site/src/lib/styles/globals.scss +++ b/apps/site/src/lib/styles/globals.scss @@ -1,4 +1,23 @@ +@use "bootstrap-utils" as bootstrap; + +$container-padding: 8rem; + .background { background-image: url("~@/assets/background/anteater-head-tiling.gif"); background-size: 464px; // half size for 2x scaling } + +.accordion { + --bs-accordion-active-color: theme.$black; + --bs-accordion-bg: transparent; + --bs-accordion-active-bg: transparent; + --bs-accordion-border-color: transparent; + --bs-accordion-border-radius: 0; + --bs-accordion-btn-icon-width: 14px; +} + +section.container { + // responsive padding + @include bootstrap.padding-top($container-padding); + @include bootstrap.padding-bottom($container-padding); +} diff --git a/apps/site/src/views/Home/sections/FAQ/FAQ.module.scss b/apps/site/src/views/Home/sections/FAQ/FAQ.module.scss index 49ce5f15..8d7702c7 100644 --- a/apps/site/src/views/Home/sections/FAQ/FAQ.module.scss +++ b/apps/site/src/views/Home/sections/FAQ/FAQ.module.scss @@ -38,14 +38,7 @@ } .accordion { - --bs-accordion-active-color: theme.$black; - --bs-accordion-bg: transparent; - --bs-accordion-active-bg: transparent; - --bs-accordion-border-color: transparent; - --bs-accordion-btn-focus-box-shadow: 0; - --bs-accordion-border-radius: 0; --bs-accordion-btn-icon-width: 14px; - --bs-accordion-btn-icon: url("~@/assets/icons/plus-lg.svg"); --bs-accordion-btn-active-icon: url("~@/assets/icons/dash-lg.svg"); } diff --git a/apps/site/src/views/Schedule/Schedule.module.scss b/apps/site/src/views/Schedule/Schedule.module.scss index e69de29b..1919760f 100644 --- a/apps/site/src/views/Schedule/Schedule.module.scss +++ b/apps/site/src/views/Schedule/Schedule.module.scss @@ -0,0 +1,21 @@ +@use "bootstrap-utils" as bootstrap; + +$container-padding: 8rem; + +.schedule { + h1 { + text-align: center; + + @include bootstrap.rfs(8rem, margin-bottom); + } + + margin: 10rem 1rem; + + @include bootstrap.media-breakpoint-up(md) { + margin: 10rem 7rem; + } + + h2 { + text-align: center; + } +} diff --git a/apps/site/src/views/Schedule/Schedule.tsx b/apps/site/src/views/Schedule/Schedule.tsx index 29d9b621..3c43e230 100644 --- a/apps/site/src/views/Schedule/Schedule.tsx +++ b/apps/site/src/views/Schedule/Schedule.tsx @@ -1,5 +1,22 @@ -import "./Schedule.module.scss"; +import ClipboardSchedule from "./sections/ClipboardSchedule/ClipboardSchedule"; +import styles from "./Schedule.module.scss"; export default function Schedule() { - return

Schedule

; + return ( +
+

Schedule

+ +
+ ); } diff --git a/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.module.scss b/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.module.scss new file mode 100644 index 00000000..47a9d0eb --- /dev/null +++ b/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.module.scss @@ -0,0 +1,36 @@ +@use "bootstrap-utils" as bootstrap; +@use "zothacks-theme" as theme; + +.accordion { + --bs-accordion-btn-icon: url("~@/assets/icons/accordion-btn.svg"); + --bs-accordion-btn-active-icon: url("~@/assets/icons/accordion-btn.svg"); + --bs-accordion-btn-icon-width: 25px; + + button::after { + margin-left: 1rem; + } +} + +.clip { + position: absolute; + width: 75%; + top: 0; + left: 50%; + transform: translate(-50%, -55%); + + @include bootstrap.media-breakpoint-up(lg) { + width: 60%; + } +} + +.clipboard { + @include bootstrap.rfs(7.5rem, border-radius); + + background-color: white; + border: 1.25rem solid theme.$brown; +} + +.accordionItem { + border-top: 2px solid theme.$light-blue; + border-bottom: 2px solid theme.$light-blue; +} diff --git a/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.tsx b/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.tsx new file mode 100644 index 00000000..1c21e2ae --- /dev/null +++ b/apps/site/src/views/Schedule/sections/ClipboardSchedule/ClipboardSchedule.tsx @@ -0,0 +1,61 @@ +"use client"; + +import Image from "next/image"; + +import Accordion from "react-bootstrap/Accordion"; +import Container from "react-bootstrap/Container"; +import Col from "react-bootstrap/Col"; +import Row from "react-bootstrap/Row"; + +import clip from "@/assets/images/clip.svg"; + +import styles from "./ClipboardSchedule.module.scss"; + +interface ClipboardScheduleProps { + schedule: { + _key: string; + title: string; + description: string; + location: string; + startDate: Date; + endDate: Date; + }[]; +} + +function ClipboardSchedule({ schedule }: ClipboardScheduleProps) { + return ( + +
+ Clipboard clip +
+

Countdown Timer

+ + {schedule.map( + ( + { _key, title, description, location, startDate, endDate }, + index, + ) => ( + + +

{title}

+ + {location}, {startDate.toString()} - {endDate.toString()} + +
+ {description} +
+ ), + )} +
+
+ ); +} + +export default ClipboardSchedule; From 3a8f7c798f79a7bc232d54596e9518b5f58cf9aa Mon Sep 17 00:00:00 2001 From: Alexander Liu Date: Sun, 29 Oct 2023 14:30:34 -0700 Subject: [PATCH 5/6] fix: properly case event schema field titles --- apps/sanity/schemas/event.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/sanity/schemas/event.ts b/apps/sanity/schemas/event.ts index 0245bc39..d408e89a 100644 --- a/apps/sanity/schemas/event.ts +++ b/apps/sanity/schemas/event.ts @@ -1,4 +1,4 @@ -import { defineType, defineField} from "sanity"; +import { defineType, defineField } from "sanity"; export default defineType({ name: "event", @@ -7,28 +7,28 @@ export default defineType({ fields: [ defineField({ name: "title", - title: "title", - type: "string" + title: "Title", + type: "string", }), defineField({ name: "startTime", - title: "startTime", - type: "datetime" + title: "Start Time", + type: "datetime", }), defineField({ name: "endTime", - title: "endTime", - type: "datetime" + title: "End Time", + type: "datetime", }), defineField({ name: "category", - title: "category", - type: "string" + title: "Category", + type: "string", }), defineField({ name: "host", - title: "host", - type: "string" + title: "Host", + type: "string", }), defineField({ name: "description", From ff15acfb07ed1a9a3879d615f92527bf66b3db50 Mon Sep 17 00:00:00 2001 From: Alexander Liu Date: Sun, 29 Oct 2023 14:41:51 -0700 Subject: [PATCH 6/6] feature: Sticker Positioning (#76) * update: removed deadzone * feat: position stickers relative to page elements * refactor: centralize sticker positioning logic to base sticker component * fix: position value wrapped with quotes * refactor: remove unnecessary forwardRef on sticker * feat: sticker positioning component * fix: remove extraneous broken sticker layout component * feat: remove hack sticker from button --------- Co-authored-by: Tyler Yu --- .../Sticker/BaseSticker.module.scss | 4 +- .../src/components/Sticker/BaseSticker.tsx | 20 +++++-- .../Sticker/StickerPosition.module.scss | 12 ++++ .../components/Sticker/StickerPosition.tsx | 56 +++++++++++++++++++ .../HackSticker/HackSticker.module.scss | 3 - .../Stickers/HackSticker/HackSticker.tsx | 28 +++++----- .../Stickers/HeartSticker/HeartSticker.tsx | 31 +++++----- .../Sticker/Stickers/stickerProps.ts | 4 ++ apps/site/src/views/Home/Home.tsx | 3 - .../ApplyButton/ApplyButton.module.scss | 3 +- .../components/ApplyButton/ApplyButton.tsx | 30 +++++++--- .../StickerLayout/StickerLayout.tsx | 16 ------ .../views/Home/sections/Landing/Landing.tsx | 3 +- 13 files changed, 142 insertions(+), 71 deletions(-) create mode 100644 apps/site/src/components/Sticker/StickerPosition.module.scss create mode 100644 apps/site/src/components/Sticker/StickerPosition.tsx delete mode 100644 apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.module.scss create mode 100644 apps/site/src/components/Sticker/Stickers/stickerProps.ts delete mode 100644 apps/site/src/views/Home/components/StickerLayout/StickerLayout.tsx diff --git a/apps/site/src/components/Sticker/BaseSticker.module.scss b/apps/site/src/components/Sticker/BaseSticker.module.scss index 775c4965..996b0e97 100644 --- a/apps/site/src/components/Sticker/BaseSticker.module.scss +++ b/apps/site/src/components/Sticker/BaseSticker.module.scss @@ -1,3 +1,5 @@ -.stickerContainer { +.sticker { cursor: grab; + position: absolute; + z-index: 100; } diff --git a/apps/site/src/components/Sticker/BaseSticker.tsx b/apps/site/src/components/Sticker/BaseSticker.tsx index 10f4d7c6..ad77726b 100644 --- a/apps/site/src/components/Sticker/BaseSticker.tsx +++ b/apps/site/src/components/Sticker/BaseSticker.tsx @@ -1,8 +1,9 @@ "use client"; +import { MutableRefObject, useRef } from "react"; import { motion } from "framer-motion"; + import styles from "./BaseSticker.module.scss"; -import { MutableRefObject, useRef } from "react"; interface StickerProps { imageSrc: string; @@ -14,9 +15,11 @@ interface StickerProps { // dragConstraints prop can be an object containing coordinates, a Falsy boolean, or a parent ref (https://www.framer.com/motion/gestures/#:~:text=%23-,dragConstraints%3A,-false%20%7C%20Partial%3CBoundingBox2D) animate?: object | undefined; transition?: object | undefined; + offsetX?: number; + offsetY?: number; } -export default function Sticker({ +const BaseSticker: React.FC = ({ imageSrc, alt, height = 100, @@ -25,7 +28,9 @@ export default function Sticker({ dragConstraints = false, animate = {}, transition = {}, -}: StickerProps) { + offsetX = 0, + offsetY = 0, +}) => { // prevent next from throwing error involving DOM API const pageRef = useRef( typeof document !== "undefined" ? document.documentElement : undefined, @@ -53,6 +58,7 @@ export default function Sticker({ filter: `drop-shadow(10px 14px 10px rgba(0, 0, 0, 0.2))`, }, drag: true, + initial: { x: -width / 2 + offsetX, y: -height / 2 + offsetY }, dragMomentum: false, dragConstraints: dragConstraints ? dragConstraints : pageRef, dragElastic: 0.2, @@ -62,13 +68,15 @@ export default function Sticker({ return ( ); -} +}; + +export default BaseSticker; diff --git a/apps/site/src/components/Sticker/StickerPosition.module.scss b/apps/site/src/components/Sticker/StickerPosition.module.scss new file mode 100644 index 00000000..a9bd3cdf --- /dev/null +++ b/apps/site/src/components/Sticker/StickerPosition.module.scss @@ -0,0 +1,12 @@ +.stickerPosition { + position: relative; + display: flex; + justify-content: center; + width: max-content; +} + +.stickerParent { + position: relative; + width: 0; + height: 0; +} diff --git a/apps/site/src/components/Sticker/StickerPosition.tsx b/apps/site/src/components/Sticker/StickerPosition.tsx new file mode 100644 index 00000000..445796cc --- /dev/null +++ b/apps/site/src/components/Sticker/StickerPosition.tsx @@ -0,0 +1,56 @@ +import type { StickerProps } from "./Stickers/stickerProps"; +import styles from "./StickerPosition.module.scss"; + +interface Sticker { + Node: React.ComponentType; + positionX?: "left" | "right"; + positionY?: "top" | "bottom"; + offsetX?: number; + offsetY?: number; +} + +const StickerParent: React.FC = ({ + Node, + positionY = "top", + offsetX, + offsetY, +}) => ( +
+ +
+); + +interface StickerPositionProps { + children?: React.ReactNode; + stickers: Sticker[]; +} + +const StickerPosition: React.FC = ({ + children, + stickers, +}) => { + return ( +
+ {stickers + .filter(({ positionX }) => !positionX || positionX === "left") + .map((sticker) => ( + // eslint-disable-next-line react/jsx-key + + ))} + {children} + {stickers + .filter(({ positionX }) => positionX === "right") + .map((sticker) => ( + // eslint-disable-next-line react/jsx-key + + ))} +
+ ); +}; + +export default StickerPosition; diff --git a/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.module.scss b/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.module.scss deleted file mode 100644 index d308296a..00000000 --- a/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.module.scss +++ /dev/null @@ -1,3 +0,0 @@ -.stickerContainer { - filter: drop-shadow(3px 5px 5px rgba(black, 0.3)); -} diff --git a/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.tsx b/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.tsx index 27b24f04..cd098ecb 100644 --- a/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.tsx +++ b/apps/site/src/components/Sticker/Stickers/HackSticker/HackSticker.tsx @@ -1,18 +1,18 @@ +import type React from "react"; +import type { StickerProps } from "../stickerProps"; import HackLogo from "@/assets/icons/hack.png"; import BaseSticker from "../../BaseSticker"; -import styles from "./HackSticker.module.scss"; import { lightShake } from "@/components/animation"; -export default function HackSticker({ style }: { style?: object | undefined }) { - return ( -
- -
- ); -} +const HackSticker: React.FC = (props) => ( + +); + +export default HackSticker; diff --git a/apps/site/src/components/Sticker/Stickers/HeartSticker/HeartSticker.tsx b/apps/site/src/components/Sticker/Stickers/HeartSticker/HeartSticker.tsx index 7d9dd148..9257901f 100644 --- a/apps/site/src/components/Sticker/Stickers/HeartSticker/HeartSticker.tsx +++ b/apps/site/src/components/Sticker/Stickers/HeartSticker/HeartSticker.tsx @@ -1,21 +1,18 @@ +import type React from "react"; +import type { StickerProps } from "../stickerProps"; import HeartEmoji from "@/assets/images/heart_emoji.png"; import BaseSticker from "../../BaseSticker"; import { fastShake } from "@/components/animation"; -export default function HeartSticker({ - style, -}: { - style?: object | undefined; -}) { - return ( -
- -
- ); -} +const HeartSticker: React.FC = (props) => ( + +); + +export default HeartSticker; diff --git a/apps/site/src/components/Sticker/Stickers/stickerProps.ts b/apps/site/src/components/Sticker/Stickers/stickerProps.ts new file mode 100644 index 00000000..054a6a1a --- /dev/null +++ b/apps/site/src/components/Sticker/Stickers/stickerProps.ts @@ -0,0 +1,4 @@ +export interface StickerProps { + offsetX?: number; + offsetY?: number; +} diff --git a/apps/site/src/views/Home/Home.tsx b/apps/site/src/views/Home/Home.tsx index ea164ae1..c2434c2d 100644 --- a/apps/site/src/views/Home/Home.tsx +++ b/apps/site/src/views/Home/Home.tsx @@ -4,14 +4,11 @@ import Mentor from "./sections/Mentor/Mentor"; import Sponsors from "./sections/Sponsors/Sponsors"; import FAQ from "./sections/FAQ/FAQ"; -import StickerLayout from "./components/StickerLayout/StickerLayout"; - import styles from "./Home.module.scss"; function Home() { return ( <> -
diff --git a/apps/site/src/views/Home/components/ApplyButton/ApplyButton.module.scss b/apps/site/src/views/Home/components/ApplyButton/ApplyButton.module.scss index 4061d64f..94c5a74b 100644 --- a/apps/site/src/views/Home/components/ApplyButton/ApplyButton.module.scss +++ b/apps/site/src/views/Home/components/ApplyButton/ApplyButton.module.scss @@ -16,10 +16,11 @@ $skew-amount: -30deg; @include bootstrap.font-size(bootstrap.$h4-font-size); - max-width: 70%; transform: skew($skew-amount); // unskew children > * { + width: max-content; + display: block; transform: skew(-$skew-amount); } diff --git a/apps/site/src/views/Home/components/ApplyButton/ApplyButton.tsx b/apps/site/src/views/Home/components/ApplyButton/ApplyButton.tsx index 0f581ca9..5c1b5ee0 100644 --- a/apps/site/src/views/Home/components/ApplyButton/ApplyButton.tsx +++ b/apps/site/src/views/Home/components/ApplyButton/ApplyButton.tsx @@ -1,17 +1,31 @@ import Button from "react-bootstrap/Button"; +import StickerPosition from "@/components/Sticker/StickerPosition"; +import { HackSticker, HeartSticker } from "@/components/Sticker/Stickers"; import styles from "./ApplyButton.module.scss"; export default function ApplyButton() { return ( - + + ); } diff --git a/apps/site/src/views/Home/components/StickerLayout/StickerLayout.tsx b/apps/site/src/views/Home/components/StickerLayout/StickerLayout.tsx deleted file mode 100644 index 5dba189f..00000000 --- a/apps/site/src/views/Home/components/StickerLayout/StickerLayout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { HeartSticker } from "@/components/Sticker/Stickers"; - -export default function StickerLayout() { - return ( - <> - - - ); -} diff --git a/apps/site/src/views/Home/sections/Landing/Landing.tsx b/apps/site/src/views/Home/sections/Landing/Landing.tsx index b9a33bef..1f9715b3 100644 --- a/apps/site/src/views/Home/sections/Landing/Landing.tsx +++ b/apps/site/src/views/Home/sections/Landing/Landing.tsx @@ -1,6 +1,5 @@ "use client"; - -import ApplyButton from "../../components/ApplyButton/ApplyButton"; +import ApplyButton from "@/views/Home/components/ApplyButton/ApplyButton"; import styles from "./Landing.module.scss";