From 1f7a0f40c006272b6bfe5a22e28356a9d3e559d3 Mon Sep 17 00:00:00 2001 From: Jennie Robinson Faber Date: Tue, 7 Oct 2025 15:07:27 +0100 Subject: [PATCH] Add Markdown support and update member features The commit adds Markdown rendering capabilities and makes several UI/UX improvements across member-related features including profile display, peer support badges, and navigation structure. Includes: - Added @tailwindcss/typography plugin - New Markdown rendering composable - Simplified member navigation links - Enhanced member profile layout and styling - Added peer support badge component - Improved mobile responsiveness - Removed redundant icons and simplified UI --- app/assets/css/main.css | 2 + app/components/AppNavigation.vue | 1 - app/components/PeerSupportBadge.vue | 87 +++++++++ app/composables/useMarkdown.js | 15 ++ app/pages/events/[id].vue | 143 +++++---------- app/pages/join.vue | 7 +- app/pages/member/dashboard.vue | 155 +++------------- app/pages/member/profile.vue | 88 ++++++---- app/pages/members.vue | 262 ++++++++++------------------ package-lock.json | 43 +++++ package.json | 4 + 11 files changed, 375 insertions(+), 432 deletions(-) create mode 100644 app/components/PeerSupportBadge.vue create mode 100644 app/composables/useMarkdown.js diff --git a/app/assets/css/main.css b/app/assets/css/main.css index e2bef36..37d236e 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -2,6 +2,8 @@ @import "tailwindcss"; @import "@nuxt/ui"; +@plugin "@tailwindcss/typography"; + @theme { /* Font families */ --font-sans: "Inter", sans-serif; diff --git a/app/components/AppNavigation.vue b/app/components/AppNavigation.vue index 812b3ba..54cd40e 100644 --- a/app/components/AppNavigation.vue +++ b/app/components/AppNavigation.vue @@ -157,7 +157,6 @@ const memberNavigationItems = [ { label: "Events", path: "/events" }, { label: "Members", path: "/members" }, { label: "Resources", path: "/resources" }, - { label: "Peer Support", path: "/peer-support" }, { label: "Profile", path: "/member/profile" }, ]; diff --git a/app/components/PeerSupportBadge.vue b/app/components/PeerSupportBadge.vue new file mode 100644 index 0000000..98f15de --- /dev/null +++ b/app/components/PeerSupportBadge.vue @@ -0,0 +1,87 @@ + + + diff --git a/app/composables/useMarkdown.js b/app/composables/useMarkdown.js new file mode 100644 index 0000000..9794192 --- /dev/null +++ b/app/composables/useMarkdown.js @@ -0,0 +1,15 @@ +import { marked } from 'marked' + +export const useMarkdown = () => { + const render = (markdown) => { + if (!markdown) return '' + return marked(markdown, { + breaks: true, + gfm: true + }) + } + + return { + render + } +} diff --git a/app/pages/events/[id].vue b/app/pages/events/[id].vue index 42820e9..7f1aba3 100644 --- a/app/pages/events/[id].vue +++ b/app/pages/events/[id].vue @@ -16,10 +16,6 @@ class="min-h-screen bg-ghost-900 flex items-center justify-center" >
-

Event Not Found

The event you're looking for doesn't exist. @@ -70,37 +66,25 @@

-
- -
-

Date

-

- {{ formatDate(event.startDate) }} -

-
+
+

Date

+

+ {{ formatDate(event.startDate) }} +

-
- -
-

Time

-

- {{ formatTime(event.startDate, event.endDate) }} -

-
+
+

Time

+

+ {{ formatTime(event.startDate, event.endDate) }} +

-
- -
-

Location

-

- {{ event.location }} -

-
+
+

Location

+

+ {{ event.location }} +

@@ -108,24 +92,16 @@
-
- -
-

- Event Cancelled -

-

- {{ event.cancellationMessage }} -

-

- This event has been cancelled. We apologize for any - inconvenience. -

-
-
+

+ Event Cancelled +

+

+ {{ event.cancellationMessage }} +

+

+ This event has been cancelled. We apologize for any + inconvenience. +

@@ -134,10 +110,6 @@
- @@ -152,7 +124,6 @@ class="mb-8" >
- Recommended for: @@ -210,14 +181,6 @@ :key="speaker.name" class="flex items-start space-x-4" > -
- -

{{ speaker.name }} @@ -249,19 +212,13 @@ class="p-4 bg-green-900/20 rounded-lg border border-green-800" >

-
- -
-

- You're registered! -

-

- We've sent a confirmation to your email -

-
+
+

+ You're registered! +

+

+ We've sent a confirmation to your email +

- -
-

- Membership Required -

-

- This event is exclusive to Ghost Guild members. Join any - circle to gain access. -

- - Become a member - - -
+

Membership Required

+

+ This event is exclusive to Ghost Guild members. Join any + circle to gain access. +

+ + Become a member → +
@@ -417,9 +365,8 @@

- events@ghostguild.org
diff --git a/app/pages/join.vue b/app/pages/join.vue index 68e806f..9590572 100644 --- a/app/pages/join.vue +++ b/app/pages/join.vue @@ -430,9 +430,10 @@ Join the community

- Get instant access to everything. Fill out your profile, agree - to our community guidelines, and complete payment (if - applicable). You'll get instant access to our community. + Get access to everything. Fill out your profile, agree to our + community guidelines, and complete payment (if applicable). + You'll get access to our community as soon as we review your + application.

diff --git a/app/pages/member/dashboard.vue b/app/pages/member/dashboard.vue index ecc6243..ab2468f 100644 --- a/app/pages/member/dashboard.vue +++ b/app/pages/member/dashboard.vue @@ -99,9 +99,6 @@ block title="Coming soon" > - Propose an Event @@ -112,9 +109,6 @@ block title="Coming soon" > - Book a Peer Session @@ -125,9 +119,6 @@ block title="Coming soon" > - Browse Resources @@ -137,130 +128,38 @@ class="border-ghost-600 text-ghost-200 hover:bg-ghost-800 hover:border-whisper-500 justify-start" block > - Update Profile + + + View Events + + + + Browse Members + + + + Manage Account +
- -
- - - -

- Upcoming Events -

-

- Discover and register for community events and workshops. -

- - -
- - - - -

Community

-

- Connect with other members in your circle and beyond. -

- - -
- - - - -

- Account Settings -

-

- Manage your profile and membership settings. -

- - -
-
- -
- -
+ @@ -927,6 +911,9 @@ const hasChanges = computed(() => { // Offering tag management const addOfferingTag = () => { const tag = currentOfferingTagInput.value.trim().replace(/,$/, ""); + if (!Array.isArray(formData.offering.tags)) { + formData.offering.tags = []; + } if (tag && !formData.offering.tags.includes(tag)) { formData.offering.tags.push(tag); currentOfferingTagInput.value = ""; @@ -934,12 +921,16 @@ const addOfferingTag = () => { }; const removeOfferingTag = (index) => { + if (!formData.offering.tags) return; formData.offering.tags.splice(index, 1); }; // Looking For tag management const addLookingForTag = () => { const tag = currentLookingForTagInput.value.trim().replace(/,$/, ""); + if (!Array.isArray(formData.lookingFor.tags)) { + formData.lookingFor.tags = []; + } if (tag && !formData.lookingFor.tags.includes(tag)) { formData.lookingFor.tags.push(tag); currentLookingForTagInput.value = ""; @@ -947,6 +938,7 @@ const addLookingForTag = () => { }; const removeLookingForTag = (index) => { + if (!formData.lookingFor.tags) return; formData.lookingFor.tags.splice(index, 1); }; @@ -964,6 +956,9 @@ const removePeerSkillTopic = (index) => { }; const addSuggestedSkillTopic = (tag) => { + if (!Array.isArray(formData.peerSupportSkillTopics)) { + formData.peerSupportSkillTopics = []; + } if (!formData.peerSupportSkillTopics.includes(tag)) { formData.peerSupportSkillTopics.push(tag); } @@ -982,22 +977,32 @@ const loadProfile = () => { // Load offering (handle both old string and new object format) if (typeof memberData.value.offering === "string") { - formData.offering = { text: memberData.value.offering, tags: [] }; + formData.offering.text = memberData.value.offering; + formData.offering.tags = []; + } else if (memberData.value.offering) { + formData.offering.text = memberData.value.offering?.text || ""; + formData.offering.tags = Array.isArray(memberData.value.offering?.tags) + ? [...memberData.value.offering.tags] + : []; } else { - formData.offering = { - text: memberData.value.offering?.text || "", - tags: memberData.value.offering?.tags || [], - }; + formData.offering.text = ""; + formData.offering.tags = []; } // Load lookingFor (handle both old string and new object format) if (typeof memberData.value.lookingFor === "string") { - formData.lookingFor = { text: memberData.value.lookingFor, tags: [] }; + formData.lookingFor.text = memberData.value.lookingFor; + formData.lookingFor.tags = []; + } else if (memberData.value.lookingFor) { + formData.lookingFor.text = memberData.value.lookingFor?.text || ""; + formData.lookingFor.tags = Array.isArray( + memberData.value.lookingFor?.tags, + ) + ? [...memberData.value.lookingFor.tags] + : []; } else { - formData.lookingFor = { - text: memberData.value.lookingFor?.text || "", - tags: memberData.value.lookingFor?.tags || [], - }; + formData.lookingFor.text = ""; + formData.lookingFor.tags = []; } formData.showInDirectory = memberData.value.showInDirectory ?? true; @@ -1006,16 +1011,29 @@ const loadProfile = () => { if (memberData.value.peerSupport) { formData.peerSupportEnabled = memberData.value.peerSupport.enabled || false; - formData.peerSupportSkillTopics = - memberData.value.peerSupport.skillTopics || []; - formData.peerSupportSupportTopics = - memberData.value.peerSupport.supportTopics || []; + formData.peerSupportSkillTopics = Array.isArray( + memberData.value.peerSupport.skillTopics, + ) + ? [...memberData.value.peerSupport.skillTopics] + : []; + formData.peerSupportSupportTopics = Array.isArray( + memberData.value.peerSupport.supportTopics, + ) + ? [...memberData.value.peerSupport.supportTopics] + : []; formData.peerSupportAvailability = memberData.value.peerSupport.availability || ""; formData.peerSupportMessage = memberData.value.peerSupport.personalMessage || ""; formData.peerSupportSlackUsername = memberData.value.peerSupport.slackUsername || ""; + } else { + formData.peerSupportEnabled = false; + formData.peerSupportSkillTopics = []; + formData.peerSupportSupportTopics = []; + formData.peerSupportAvailability = ""; + formData.peerSupportMessage = ""; + formData.peerSupportSlackUsername = ""; } // Load privacy settings (with defaults) diff --git a/app/pages/members.vue b/app/pages/members.vue index 6ca98a3..56e592a 100644 --- a/app/pages/members.vue +++ b/app/pages/members.vue @@ -119,8 +119,8 @@
Active filters: {{ circleLabels[selectedCircle] }} @@ -141,7 +141,7 @@ Offering Peer Support @@ -187,8 +187,14 @@
+ + +
@@ -207,18 +213,15 @@
- +

{{ member.name }} - +

{{ member.pronouns }}
-
+
@@ -234,114 +237,25 @@ 🕐 {{ member.timeZone }}
- - -
-
-

- {{ member.bio }} -

-
+
-
- - 💜 Offering Peer Support - +
+

+ {{ member.name }} offers 1:1 chats on: +

@@ -379,74 +293,85 @@ Availability: {{ member.peerSupport.availability }}
- - - Message {{ member.peerSupport.slackUsername }} on Slack - + +
- -
-

- Offering -

-

- {{ member.offering.description }} -

-
- + Skills Exchange + +
+ +
+
+ Can share +
+

- {{ tag }} - + {{ member.offering.description }} +

+
+ + {{ tag }} + +
-
- -
-

- Looking For -

-

- {{ member.lookingFor.description }} -

-
- +
+
+ Looking to learn +
+

- {{ tag }} - + {{ member.lookingFor.description }} +

+
+ + {{ tag }} + +
@@ -502,6 +427,7 @@