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.
This commit is contained in:
parent
3ad127ed78
commit
6e7e27ac4e
8 changed files with 885 additions and 44 deletions
810
app/assets/css/main.css
Normal file
810
app/assets/css/main.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,29 +2,47 @@
|
|||
<template>
|
||||
<div>
|
||||
<UContainer>
|
||||
<UHero>
|
||||
<template #title>
|
||||
<div class="py-24 text-center">
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
Pay what you can, take what you need, build what we dream
|
||||
</template>
|
||||
<template #description>
|
||||
</h1>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-400 mb-8">
|
||||
Ghost Guild: A solidarity-based community for game developers
|
||||
exploring cooperative models
|
||||
</template>
|
||||
<template #actions>
|
||||
<UButton to="/join" size="lg" color="purple">
|
||||
Join Ghost Guild
|
||||
</UButton>
|
||||
</template>
|
||||
</UHero>
|
||||
</p>
|
||||
<UButton to="/join" size="lg" color="primary">
|
||||
Join Ghost Guild
|
||||
</UButton>
|
||||
</div>
|
||||
|
||||
<UGrid :cols="3" class="mt-16 gap-8">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 mt-16">
|
||||
<UCard v-for="circle in circles" :key="circle.id">
|
||||
<template #header>
|
||||
<h3>{{ circle.name }}</h3>
|
||||
</template>
|
||||
{{ circle.description }}
|
||||
</UCard>
|
||||
</UGrid>
|
||||
</div>
|
||||
</UContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const circles = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Community Circle',
|
||||
description: 'Join our community for $15/month. Perfect for indie developers and students looking to connect with like-minded creators.'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Support Circle',
|
||||
description: 'Support the community at $25/month. Get access to additional resources and help sustain solidarity memberships.'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Sustaining Circle',
|
||||
description: 'Champion our mission at $50/month. Your contribution helps us provide more solidarity spots and expand our programs.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
<UContainer class="py-12">
|
||||
<UForm :state="form" @submit="handleSubmit">
|
||||
<!-- Step 1: Basic Info -->
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UFormField label="Email" name="email">
|
||||
<UInput v-model="form.email" type="email" />
|
||||
</UFormGroup>
|
||||
</UFormField>
|
||||
|
||||
<!-- Step 2: Choose Circle -->
|
||||
<URadioGroup
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, onMounted } from 'vue';
|
||||
|
||||
const form = reactive({
|
||||
email: "",
|
||||
name: "",
|
||||
|
|
@ -35,6 +37,23 @@ const form = reactive({
|
|||
contribution: "15",
|
||||
});
|
||||
|
||||
const circleOptions = [
|
||||
{ value: 'community', label: 'Community Circle - $15/month' },
|
||||
{ value: 'support', label: 'Support Circle - $25/month' },
|
||||
{ value: 'sustaining', label: 'Sustaining Circle - $50/month' }
|
||||
];
|
||||
|
||||
const contributionOptions = [
|
||||
{ value: '15', label: '$15/month' },
|
||||
{ value: '25', label: '$25/month' },
|
||||
{ value: '50', label: '$50/month' },
|
||||
{ value: 'custom', label: 'Custom amount' }
|
||||
];
|
||||
|
||||
const handleSubmit = () => {
|
||||
console.log('Form submitted:', form);
|
||||
};
|
||||
|
||||
// Load Helcim.js
|
||||
onMounted(() => {
|
||||
const script = document.createElement("script");
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<template #title> Welcome back, {{ member?.name }}! </template>
|
||||
</UDashboardHeader>
|
||||
|
||||
<UGrid :cols="2" class="gap-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<UCard>
|
||||
<template #header>Your Circle</template>
|
||||
<p class="text-xl font-semibold">{{ member?.circle }}</p>
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
Adjust Contribution
|
||||
</UButton>
|
||||
</UCard>
|
||||
</UGrid>
|
||||
</div>
|
||||
|
||||
<UCard class="mt-6">
|
||||
<template #header>Quick Links</template>
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ export default defineNuxtConfig({
|
|||
plausible: {
|
||||
domain: "ghostguild.org",
|
||||
},
|
||||
css: ["~/assets/css/main.css"],
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// server/api/auth/login.post.js
|
||||
import jwt from 'jsonwebtoken'
|
||||
import Member from '~/server/models/member'
|
||||
import Member from '../../models/member'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const { email } = await readBody(event)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,17 @@
|
|||
// server/api/members/create.post.js
|
||||
import Member from '../../models/member'
|
||||
|
||||
// server/models/member.js
|
||||
import mongoose from 'mongoose'
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event)
|
||||
|
||||
const memberSchema = new mongoose.Schema({
|
||||
email: { type: String, required: true, unique: true },
|
||||
name: { type: String, required: true },
|
||||
circle: {
|
||||
type: String,
|
||||
enum: ['community', 'founder', 'practitioner'],
|
||||
required: true
|
||||
},
|
||||
contributionTier: {
|
||||
type: String,
|
||||
enum: ['0', '5', '15', '30', '50'],
|
||||
required: true
|
||||
},
|
||||
helcimCustomerId: String,
|
||||
helcimSubscriptionId: String,
|
||||
slackInvited: { type: Boolean, default: false },
|
||||
createdAt: { type: Date, default: Date.now },
|
||||
lastLogin: Date
|
||||
try {
|
||||
const member = new Member(body)
|
||||
await member.save()
|
||||
return { success: true, member }
|
||||
} catch (error) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: error.message
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export default mongoose.model('Member', memberSchema)
|
||||
|
|
@ -21,4 +21,5 @@ const memberSchema = new mongoose.Schema({
|
|||
lastLogin: Date
|
||||
})
|
||||
|
||||
export default mongoose.model('Member', memberSchema)
|
||||
// Check if model already exists to prevent re-compilation in development
|
||||
export default mongoose.models.Member || mongoose.model('Member', memberSchema)
|
||||
Loading…
Add table
Add a link
Reference in a new issue