From 6e7e27ac4ea3f889deb2a36171f4f6c1d5fd6aab Mon Sep 17 00:00:00 2001 From: Jennie Robinson Faber Date: Tue, 26 Aug 2025 18:21:52 +0100 Subject: [PATCH] Enhance UI and functionality: Update main page layout, add contribution options in join form, and improve member dashboard display. Refactor API endpoints for member creation and login. --- app/assets/css/main.css | 810 ++++++++++++++++++++++++++++++ app/pages/index.vue | 44 +- app/pages/join.vue | 23 +- app/pages/members/index.vue | 4 +- nuxt.config.ts | 3 +- server/api/auth/login.post.js | 2 +- server/api/members/create.post.js | 40 +- server/models/member.js | 3 +- 8 files changed, 885 insertions(+), 44 deletions(-) create mode 100644 app/assets/css/main.css diff --git a/app/assets/css/main.css b/app/assets/css/main.css new file mode 100644 index 0000000..1e3ccb1 --- /dev/null +++ b/app/assets/css/main.css @@ -0,0 +1,810 @@ + +@import "tailwindcss"; +@import "@nuxt/ui"; + +@theme { + /* Font families */ + --font-sans: "Inter", "Neue Montreal", sans-serif; + --font-body: "Inter", sans-serif; + --font-mono: "Ubuntu Mono", monospace; + --font-display: "NB Television Pro", monospace; + + /* Custom colors */ + --color-lavender-50: #fcf6fd; + --color-lavender-100: #f7ebfc; + --color-lavender-200: #f0d7f7; + --color-lavender-300: #e5b7f0; + --color-lavender-400: #d689e5; + --color-lavender-500: #c25fd6; + --color-lavender-600: #a840b9; + --color-lavender-700: #8d3299; + --color-lavender-800: #752b7d; + --color-lavender-900: #622867; + --color-lavender-950: #3e0f43; + + /* Named colors for glow effects */ + --color-peachFuzz: #ffcc99; + --color-lemonChiffon: #ffff99; + --color-mintSpray: #ccff99; + --color-jadeMist: #99ff99; + --color-aquaFresh: #99ffcc; + --color-skyKiss: #99ccff; + --color-lavenderHush: #9999ff; + --color-purpleHaze: #cc99ff; + --color-pinkBliss: #ff99cc; + --color-body: #cccccc; + + /* Animations */ + --animate-float-1: ghostie1 3s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite alternate; + --animate-float-2: ghostie2 2.5s cubic-bezier(0.445, 0.05, 0.55, 0.95) infinite alternate; + --animate-float-3: ghostie3 2s cubic-bezier(0.445, 0.05, 0.55, 0.95) infinite alternate; +} + + +/* Keyframes for animations */ +@keyframes ghostie1 { + 0% { transform: translateY(0); } + 100% { transform: translateY(-20px); } +} + +@keyframes ghostie2 { + 0% { transform: translateY(0); } + 100% { transform: translateY(-15px); } +} + +@keyframes ghostie3 { + 0% { transform: translateY(0); } + 100% { transform: translateY(-10px); } +} + +.what-we-do ul { + @apply list-disc list-inside space-y-2; +} + +.what-we-do a { + @apply text-lavender-400 hover:text-lavender-300 transition-colors; +} + +.gradient-text { + @apply text-zinc-50 text-2xl md:text-4xl; + + a& { + text-decoration: underline; + } +} + + +.glow-bg { + position: relative; +} +/* Force dark mode by default - ensures no flash of light content */ +html { + color-scheme: dark; +} + +body { + @apply font-sans antialiased text-zinc-300 bg-zinc-800; + /* background-image: url(/img/background_top_edge.png); */ + background-repeat: repeat-x; + background-size: 20%; + + a:not(.glow-link), a:not(.cta-button) { + @apply hover:brightness-125; + } +} +main { + /* @apply pb-0; */ +} +body, +.rainbow-border { + /* border-top: 1px solid; + border-image: linear-gradient( + to right, + #ff9999, + #ffcc99, + #ffff99, + #ccff99, + #99ff99, + #99ffcc, + #99ccff, + #9999ff, + #cc99ff, + #ff99cc + ); + border-image-slice: 1; */ +} + + +.gradient-header::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + height: 1px; + width: 100%; + background: linear-gradient( + to right, + #ff9999, + #ffcc99, + #ffff99, + #ccff99, + #99ff99, + #99ffcc, + #99ccff, + #9999ff, + #cc99ff, + #ff99cc + ); +} +.gradient-border { + position: relative; +} + +.gradient-border::before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + margin: -2px; /* Adjust to your desired border width */ + border-radius: inherit; + background: linear-gradient( + to right, + #ff9999, + #ffcc99, + #ffff99, + #ccff99, + #99ff99, + #99ffcc, + #99ccff, + #9999ff, + #cc99ff, + #ff99cc + ); +} +@define-mixin text-crt $size { + /* background-image: url("~/assets/img/CRT_screen_pattern_11x16.png"); + background-repeat: repeat; + background-size: 50%; + background-clip: text; + -webkit-background-clip: text; */ + /* mix-blend-mode: exclusion; */ + /* color: transparent; color: rgba(245, 235, 237, 0.7); */ + /* letter-spacing: -1px; */ + /* Adjusting the opacity and spread of the white shadow based on size */ + text-shadow: 2px 0 4px rgba(220, 148, 232, 1), + -2px 0 4px rgba(92, 201, 245, 1), + 0 0 10px rgba(255, 255, 255, 0.22); +} +h1 { + .text-bg { + @apply text-purple-400; + } + font-family: "NB Television Pro", monospace; + letter-spacing: -1px; + font-smooth: auto; + -webkit-font-smoothing: auto; +} + +h2 { + font-family: "NB Television Pro", monospace; + @apply text-3xl; + font-smooth: auto; + -webkit-font-smoothing: auto; + /* @mixin text-crt 0.5; */ +} + +h3 { + @apply uppercase text-2xl font-bold text-lavender-300 mb-0 tracking-wide; + font-family: "NB Television Pro", monospace; + @apply text-3xl mt-8; + font-smooth: auto; + -webkit-font-smoothing: auto; + @mixin text-crt 0.3; + /* letter-spacing: -1px; */ +} + + +.font-display { + font-family: "NB Television Pro", monospace; + font-smooth: auto; + -webkit-font-smoothing: auto; +} +nav { + ul { + li { + a { + font-family: "NB Television Pro", monospace; + @apply text-2xl; + } + } + } +} +p, +li { + @apply font-normal; + strong, + b { + @apply font-bold brightness-125; + } +} + +.text-prose { + @screen md { + @apply mt-5 text-xl; + } + + p { + @apply mt-3 mx-auto max-w-4xl; + + @screen sm { + @apply text-lg; + } + } +} +.bg-zinc-300 { + @apply text-zinc-900; +} + +section { + @apply mb-16 px-6 max-w-7xl; + p a, + li a { + @apply hover:brightness-125 underline; + } + + &:last-child { + /* @apply mb-0; */ + } + section { + @apply px-0 mb-0; + } + + &.wide { + @apply mb-0; + } + @screen md { + /* @apply mb-24 px-12; */ + } + /* todo fix this situation */ + + @screen lg { + &:last-child { + /* @apply mb-0; */ + } + } + p { + @apply mt-3; + } + p, + li { + @apply text-base; + + @screen sm { + @apply text-lg; + } + } + + h2 { + @apply flex-1 mb-2; + } +} +.text-arrow { + @mixin text-crt 0.3; +} +.page--news { + .article-title--excerpt { + @apply text-xl md:text-2xl font-bold text-zinc-200; + } +} +.page--about { + #staff-cards { + /* these are here because we need access to the mixin */ + h2 { + @mixin text-crt 0.4; + @apply text-3xl font-bold text-zinc-300 my-0; + } + h3 { + @apply uppercase font-body text-xs text-zinc-300 mt-0 mb-2 tracking-normal; + } + /* @screen md { + h2 { + @apply text-xl my-0; + } + } */ + } +} + +.page--baby-ghosts { + main { + ul { + @apply list-none m-0 mt-4 p-0; + + li { + @apply relative pl-6 mb-3; + + &:before { + content: "–"; + @apply absolute left-0 top-0; + } + } + } + } + li > ul { + @apply mt-0; + li { + @apply mb-0; + } + } + li, + p { + a { + @apply text-zinc-200 hover:text-zinc-50; + } + } + div + div h3:first-child { + @apply mt-0; + } + h3 { + @apply mt-8 leading-10 mb-0; + + &#coordinators { + @apply lg:mt-0 mt-12; + } + } + section { + @apply px-6; + + &:not(.header):not(.wide) { + @apply text-zinc-300; + } + } + + .timeline { + h4 { + @apply text-2xl leading-10 mt-12 font-bold text-zinc-100 uppercase text-primary; + } + h5 { + @apply text-base mb-6; + } + + strong, + b { + @apply font-bold text-zinc-200; + } + } + + .right-aligner { + h3 { + @apply mb-4 lg:mb-0 lg:text-right text-4xl; + } + ul { + @apply mt-0; + } + } + .cta { + @apply mx-auto w-full text-center pb-12; + @screen md { + @apply pb-0; + } + } + .action-buttons { + @apply flex flex-wrap justify-around my-12; + @screen lg { + @apply my-0; + } + .cta { + @apply inline w-full md:w-1/2 mb-6 md:mb-0; + &:last-child { + @apply mb-0; + } + } + } + h3:not(:first-child), + h4:not(:first-child) { + @apply mt-10; + } +} +.bg-ghostie { + + &.ghostie-double-take { + background-image: url(/img/ghosts/Ghost-Double-Take.svg); + } + &.ghostie-sweet { + background-image: url(/img/ghosts/Ghost-Sweet.svg); + } + &.ghostie-happy { + background-image: url(/img/ghosts/Ghost-Happy.svg); + } + background-repeat: no-repeat; + background-position: right -10px bottom -50px; + background-size: 200px; + background-image: none; + overflow: hidden; + &.flip { + transform: scaleX(-1); + } + /* p, + li { + @apply bg-zinc-300; + } */ +} + +@keyframes wiggle { + 0% { + transform: rotate(0deg); + } + 25% { + transform: rotate(-5deg); + } + 50% { + transform: rotate(0deg); + } + 75% { + transform: rotate(5deg); + } + 100% { + transform: rotate(0deg); + } +} + +@define-mixin glow $color { + text-shadow: 0 0 10px $color, 0 0 20px $color, 0 0 30px $color, + 0 0 40px $color; +} +.router-link-active { + @apply text-white; +} +.glow-link { + @apply no-underline inline-block transition-all duration-300 ease-in-out mr-4; + &.router-link-exact-active { + @apply text-zinc-50; + } + &.peachFuzz { + &:hover, + &.router-link-exact-active { + @mixin glow #ffcc99; + } + } + + &.lemonChiffon { + &:hover, + &.router-link-exact-active { + @mixin glow #ffff99; + } + } + + &.mintSpray { + &:hover, + &.router-link-exact-active { + @mixin glow #ccff99; + } + } + + &.jadeMist { + &:hover, + &.router-link-exact-active { + @mixin glow #99ff99; + } + } + + &.aquaFresh { + &:hover, + &.router-link-exact-active { + @mixin glow #99ffcc; + } + } + + &.skyKiss { + &:hover, + &.router-link-exact-active { + @mixin glow #99ccff; + } + } + + &.lavenderHush { + &:hover, + &.router-link-exact-active { + @mixin glow #9999ff; + } + } + + &.purpleHaze { + &:hover, + &.router-link-exact-active { + @mixin glow #cc99ff; + } + } + + &.pinkBliss { + &:hover, + &.router-link-exact-active { + @mixin glow #ff99cc; + } + } +} +.article-title--excerpt { + @apply text-xl font-bold font-body; +} +.article-title { + @mixin text-crt 0.3; +} +article { + h2 { + @apply text-3xl font-bold mt-8; + } + h3 { + @apply text-2xl font-bold mt-8 uppercase; + } + ul, + ol { + @apply list-none m-0 mt-4 p-0; + + li { + @apply relative pl-6; + + &:before { + content: "–"; + @apply absolute left-0 top-0; + } + } + } +} +ul.formkit-messages { + @apply list-none mt-2 ml-0 p-0 m-0; + li { + @apply relative p-0 m-0; + + &:before { + content: "" !important; + position: absolute; + left: 0; + top: 0; + } + } + .formkit-message { + @apply text-sm inline-block bg-red-300 text-zinc-800 p-2 leading-tight font-bold; + } +} +.glow-bg { + @apply bg-zinc-800; + box-shadow: calc(4px) 0 calc(4px) rgba(220, 148, 232, 1), + calc(-2px) 0 calc(4px) rgba(92, 201, 245, 1), + 0 0 calc(10px) rgba(255, 255, 255, calc(0.1)); +} +.float-section { + h2 { + @apply text-2xl md:text-6xl font-bold text-zinc-300; + } + p { + @apply text-lg md:text-2xl lg:text-3xl text-zinc-300; + } +} +.page--home { + .what-we-do { + ul { + @apply list-none m-0 mt-4 p-0; + + li { + @apply relative pl-6; + + &:before { + content: "–"; + @apply absolute left-0 top-0; + } + } + } + li, + p { + @apply md:text-2xl; + a { + @apply text-zinc-200 hover:text-zinc-50; + } + } + } +} + +.grain-wrapper { + position: fixed; + z-index: 100; + pointer-events: none; +} + +.grain { + mix-blend-mode: hard-light; + height: 100vh; + width: 100vw; + background-image: url(~/assets/img/noise-256w.png); + opacity: 0.1; + + animation: grain 0.4s steps(1) infinite; +} +@media (prefers-reduced-motion) { + .grain { + animation: none; + } +} +@keyframes grain { + 0%, + 100% { + background-position: 0% 0%; + } + 20% { + background-position: 50% 50%; + } + 40% { + background-position: 25% 25%; + } + 60% { + background-position: 75% 75%; + } + 80% { + background-position: 0% 100%; + } +} +.activities-table { + table { + @apply w-full; + } + tbody { + @apply space-y-4; + } + thead { + @apply text-left; + } + th { + @apply text-xl font-bold; + } + td { + @apply text-lg; + } + .activity { + @apply text-lg; + } +} + +/* Time Commitment List Styles */ +.page--peer-support .time-commitment ul, +.page--application ul.eligibility { + @apply space-y-1 text-lg text-zinc-300 mt-2; + li { + @apply pl-6 relative; + &:before { + content: "•"; + @apply absolute left-0 text-lavender-500; + } + } +} + +/* CTA Button Dithered Shadow Effect */ +.cta-button { + position: relative; + isolation: isolate; +} + +.cta-button::before { + content: ""; + position: absolute; + inset: 0; + border-radius: 9999px; + z-index: -2; + background-image: + repeating-linear-gradient( + 45deg, + transparent, + transparent 1px, + rgba(0, 0, 0, 0.3) 1px, + rgba(0, 0, 0, 0.3) 2px + ), + repeating-linear-gradient( + -45deg, + transparent, + transparent 1px, + rgba(0, 0, 0, 0.2) 1px, + rgba(0, 0, 0, 0.2) 2px + ); + transform: translate(4px, 4px); + transition: transform 0.3s ease; +} + +.cta-button::after { + content: ""; + position: absolute; + inset: 0; + border-radius: 9999px; + z-index: -1; + background-image: url('~/assets/img/noise-256w.png'); + background-size: 100px 100px; + opacity: 0.15; + mix-blend-mode: multiply; + transform: translate(6px, 6px); + transition: transform 0.3s ease; +} + +.cta-button:hover::before { + transform: translate(6px, 6px); +} + +.cta-button:hover::after { + transform: translate(8px, 8px); +} + +/* Color variations for dithered shadows */ +.cta-peach::before { + background-image: + repeating-linear-gradient( + 45deg, + transparent, + transparent 1px, + rgba(255, 153, 102, 0.3) 1px, + rgba(255, 153, 102, 0.3) 2px + ), + repeating-linear-gradient( + -45deg, + transparent, + transparent 1px, + rgba(255, 204, 153, 0.2) 1px, + rgba(255, 204, 153, 0.2) 2px + ); +} + +.cta-blue::before { + background-image: + repeating-linear-gradient( + 45deg, + transparent, + transparent 1px, + rgba(37, 99, 235, 0.3) 1px, + rgba(37, 99, 235, 0.3) 2px + ), + repeating-linear-gradient( + -45deg, + transparent, + transparent 1px, + rgba(6, 182, 212, 0.2) 1px, + rgba(6, 182, 212, 0.2) 2px + ); +} + +.cta-green::before { + background-image: + repeating-linear-gradient( + 45deg, + transparent, + transparent 1px, + rgba(34, 197, 94, 0.3) 1px, + rgba(34, 197, 94, 0.3) 2px + ), + repeating-linear-gradient( + -45deg, + transparent, + transparent 1px, + rgba(52, 211, 153, 0.2) 1px, + rgba(52, 211, 153, 0.2) 2px + ); +} + + +.quotes { + @apply p-6 xl:p-0 justify-around text-zinc-300; + p { + @apply block w-full text-xl; + @screen lg { + @apply w-1/3; + } + &:first-child { + @apply block text-2xl w-full; + @screen lg { + @apply w-3/5; + } + } + .attribution { + @apply text-base; + } + } + ul { + @apply mt-0; + } + } \ No newline at end of file diff --git a/app/pages/index.vue b/app/pages/index.vue index cfbda18..5855392 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -2,29 +2,47 @@ + + diff --git a/app/pages/join.vue b/app/pages/join.vue index 05d84b5..73c7249 100644 --- a/app/pages/join.vue +++ b/app/pages/join.vue @@ -3,9 +3,9 @@ - + - +