From 61d33f5db3d87965dfe3a56f0ae7be399bb164a7 Mon Sep 17 00:00:00 2001 From: Jennie Robinson Faber Date: Tue, 14 Apr 2026 17:17:09 +0100 Subject: [PATCH] feat(board): replace profile board section with posts list --- app/pages/member/profile.vue | 266 ++++++++++++++++++++++------------- 1 file changed, 169 insertions(+), 97 deletions(-) diff --git a/app/pages/member/profile.vue b/app/pages/member/profile.vue index ca0381b..384c186 100644 --- a/app/pages/member/profile.vue +++ b/app/pages/member/profile.vue @@ -165,73 +165,48 @@
Board
- - Slack Handle + - -
- -
- - -
- {{ formData.boardDetails?.length || 0 }} / 300 +
+ Shown on your board posts so other members can reach out.
-
- -
- Offer Peer Support - Share your Slack handle so other members can reach out -
+
+
Your Posts
+ + New Post
-
-
- - -
+
+ No posts yet. + + Visit the Board + + to share what you're seeking or offering. +
-
- - -
- -
- - -
- {{ formData.boardPersonalMessage?.length || 0 }} / 200 +
    +
  • +
    +
    {{ post.title }}
    +
    {{ postExcerpt(post) }}
    -
-
+
+ Edit + +
+ + @@ -296,6 +271,8 @@ definePageMeta({ const { memberData, checkMemberStatus } = useAuth(); const { openLoginModal } = useLoginModal(); +const { posts: myPosts, fetchPosts, deletePost } = useBoardPosts(); +const toast = useToast(); const availableGhosts = [ { value: "disbelieving", label: "Disbelieving", image: "/ghosties/Ghost-Disbelieving.png" }, @@ -316,9 +293,6 @@ const { data: tagsData } = await useFetch("/api/tags"); const craftTags = computed(() => (tagsData.value?.tags || []).filter((t) => t.pool === "craft"), ); -const cooperativeTags = computed(() => - (tagsData.value?.tags || []).filter((t) => t.pool === "cooperative"), -); const showTagSuggestModal = ref(false); const tagSuggestPool = ref(""); @@ -339,13 +313,7 @@ const formData = reactive({ showInDirectory: true, craftTags: [], craftTagsPrivacy: "members", - boardTopics: [], - boardPrivacy: "members", - boardDetails: "", - boardOfferPeerSupport: false, - boardAvailability: "", boardSlackHandle: "", - boardPersonalMessage: "", pronounsPrivacy: "members", timeZonePrivacy: "members", avatarPrivacy: "members", @@ -388,12 +356,7 @@ const loadProfile = () => { : []; const board = memberData.value.board || {}; - formData.boardTopics = Array.isArray(board.topics) ? [...board.topics] : []; - formData.boardOfferPeerSupport = board.offerPeerSupport ?? false; - formData.boardAvailability = board.availability || ""; formData.boardSlackHandle = board.slackHandle || ""; - formData.boardPersonalMessage = board.personalMessage || ""; - formData.boardDetails = board.details || ""; const privacy = memberData.value.privacy || {}; formData.pronounsPrivacy = privacy.pronouns || "members"; @@ -403,7 +366,6 @@ const loadProfile = () => { formData.bioPrivacy = privacy.bio || "members"; formData.locationPrivacy = privacy.location || "members"; formData.craftTagsPrivacy = privacy.craftTags || "members"; - formData.boardPrivacy = privacy.board || "members"; const notifs = memberData.value.notifications || {}; formData.notifications.events = notifs.events ?? true; @@ -418,23 +380,10 @@ const handleSubmit = async () => { saveError.value = null; try { - await Promise.all([ - $fetch("/api/members/profile", { - method: "PATCH", - body: { ...formData }, - }), - $fetch("/api/members/me/board", { - method: "PATCH", - body: { - topics: formData.boardTopics, - offerPeerSupport: formData.boardOfferPeerSupport, - availability: formData.boardAvailability, - slackHandle: formData.boardSlackHandle, - personalMessage: formData.boardPersonalMessage, - details: formData.boardDetails, - }, - }), - ]); + await $fetch("/api/members/profile", { + method: "PATCH", + body: { ...formData }, + }); saveSuccess.value = true; @@ -477,8 +426,33 @@ onMounted(async () => { } loadProfile(); + + if (memberId.value) { + await fetchPosts({ author: memberId.value }); + } }); +const postExcerpt = (post) => { + const text = post.seeking || post.offering || ""; + if (text.length <= 80) return text; + return text.slice(0, 80).trimEnd() + "..."; +}; + +const handleDeletePost = async (post) => { + if (!window.confirm(`Delete "${post.title}"?`)) return; + try { + await deletePost(post._id); + await fetchPosts({ author: memberId.value }); + } catch (error) { + console.error("Delete post error:", error); + toast.add({ + title: "Failed to delete post", + description: error.data?.message || "Please try again.", + color: "error", + }); + } +}; + onBeforeUnmount(() => { if (saveSuccessTimer) clearTimeout(saveSuccessTimer); }); @@ -612,13 +586,111 @@ useHead({ margin-top: 1px; } -/* ---- CONNECTIONS PANEL ---- */ -.connections-panel { - border: 1px dashed var(--border); - padding: 12px 16px; +/* ---- FIELD HELPER TEXT ---- */ +.field-help { + font-size: 11px; + color: var(--text-faint); margin-top: 4px; - margin-bottom: 12px; - background: var(--surface); +} + +/* ---- YOUR POSTS LIST ---- */ +.posts-header { + display: flex; + align-items: baseline; + justify-content: space-between; + margin-top: 20px; + margin-bottom: 8px; +} + +.posts-heading { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--text-dim); +} + +.posts-new-link { + font-size: 12px; + color: var(--candle); + text-decoration: none; +} + +.posts-new-link:hover { + text-decoration: underline; +} + +.posts-empty { + font-size: 12px; + color: var(--text-faint); + padding: 12px 0; + border-top: 1px dashed var(--border); +} + +.posts-empty-link { + color: var(--candle); + text-decoration: none; +} + +.posts-empty-link:hover { + text-decoration: underline; +} + +.posts-list { + list-style: none; + margin: 0; + padding: 0; + border-top: 1px dashed var(--border); +} + +.post-item { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + padding: 10px 0; + border-bottom: 1px dashed var(--border); +} + +.post-body { + flex: 1; + min-width: 0; +} + +.post-title { + font-size: 13px; + color: var(--text); + margin-bottom: 2px; +} + +.post-excerpt { + font-size: 11px; + color: var(--text-faint); + line-height: 1.4; +} + +.post-actions { + display: flex; + gap: 10px; + flex-shrink: 0; +} + +.post-action { + font-size: 11px; + color: var(--candle); + background: none; + border: none; + padding: 0; + cursor: pointer; + text-decoration: none; + font-family: inherit; +} + +.post-action:hover { + text-decoration: underline; +} + +.post-action-danger { + color: var(--ember); } /* ---- DISABLED BUTTON ---- */