Rename communityEcology → board across frontend, add Board nav, update redirects
- Add Board to exploreItems in AppNavigation - Update ecology.vue + connections.vue redirects to /board - Rename all communityEcology refs to board in member profiles, dashboard, admin, onboarding - Update API path /api/members/me/community-ecology → /api/members/me/board
This commit is contained in:
parent
3e5cedb1a6
commit
cdef868256
9 changed files with 75 additions and 76 deletions
|
|
@ -210,6 +210,7 @@ const youItems = [
|
||||||
const exploreItems = [
|
const exploreItems = [
|
||||||
{ label: "Events", path: "/events" },
|
{ label: "Events", path: "/events" },
|
||||||
{ label: "Members", path: "/members" },
|
{ label: "Members", path: "/members" },
|
||||||
|
{ label: "Board", path: "/board" },
|
||||||
{ label: "Wiki", path: "https://wiki.ghostguild.org", external: true },
|
{ label: "Wiki", path: "https://wiki.ghostguild.org", external: true },
|
||||||
{ label: "About", path: "/about" },
|
{ label: "About", path: "/about" },
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ const { goals, isComplete, currentSuggestion, trackGoal, loading } = useOnboardi
|
||||||
|
|
||||||
const completedCount = computed(() => {
|
const completedCount = computed(() => {
|
||||||
const g = goals.value
|
const g = goals.value
|
||||||
return [g.hasProfileTags, g.hasVisitedEvent, g.hasEngagedEcology, g.hasClickedWiki]
|
return [g.hasProfileTags, g.hasVisitedEvent, g.hasEngagedBoard, g.hasClickedWiki]
|
||||||
.filter(Boolean).length
|
.filter(Boolean).length
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export function useOnboarding(options = {}) {
|
||||||
const goals = useState('onboarding.goals', () => ({
|
const goals = useState('onboarding.goals', () => ({
|
||||||
hasProfileTags: false,
|
hasProfileTags: false,
|
||||||
hasVisitedEvent: false,
|
hasVisitedEvent: false,
|
||||||
hasEngagedEcology: false,
|
hasEngagedBoard: false,
|
||||||
hasClickedWiki: false,
|
hasClickedWiki: false,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ export function useOnboarding(options = {}) {
|
||||||
const loading = useState('onboarding.loading', () => false)
|
const loading = useState('onboarding.loading', () => false)
|
||||||
const recommendations = useState('onboarding.recommendations', () => ({
|
const recommendations = useState('onboarding.recommendations', () => ({
|
||||||
events: [],
|
events: [],
|
||||||
ecology: [],
|
board: [],
|
||||||
wiki: [],
|
wiki: [],
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ export function useOnboarding(options = {}) {
|
||||||
!!completedAt.value ||
|
!!completedAt.value ||
|
||||||
(goals.value.hasProfileTags &&
|
(goals.value.hasProfileTags &&
|
||||||
goals.value.hasVisitedEvent &&
|
goals.value.hasVisitedEvent &&
|
||||||
goals.value.hasEngagedEcology &&
|
goals.value.hasEngagedBoard &&
|
||||||
goals.value.hasClickedWiki)
|
goals.value.hasClickedWiki)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -52,12 +52,12 @@ export function useOnboarding(options = {}) {
|
||||||
actionText: 'Browse events',
|
actionText: 'Browse events',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!goals.value.hasEngagedEcology) {
|
if (!goals.value.hasEngagedBoard) {
|
||||||
return {
|
return {
|
||||||
key: 'ecology',
|
key: 'board',
|
||||||
text: 'Explore the community ecology to find collaborators',
|
text: 'Explore the board to find collaborators',
|
||||||
action: '/ecology',
|
action: '/board',
|
||||||
actionText: 'Explore ecology',
|
actionText: 'Explore board',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!goals.value.hasClickedWiki) {
|
if (!goals.value.hasClickedWiki) {
|
||||||
|
|
@ -72,7 +72,7 @@ export function useOnboarding(options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Graduated — suggestion mode
|
// Graduated — suggestion mode
|
||||||
const cats = ['events', 'ecology', 'wiki'].filter(
|
const cats = ['events', 'board', 'wiki'].filter(
|
||||||
(c) => recommendations.value[c]?.length > 0
|
(c) => recommendations.value[c]?.length > 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -99,12 +99,12 @@ export function useOnboarding(options = {}) {
|
||||||
actionText: 'View event',
|
actionText: 'View event',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (category === 'ecology') {
|
if (category === 'board') {
|
||||||
return {
|
return {
|
||||||
key: 'ecology',
|
key: 'board',
|
||||||
text: `Connect with ${item.name || 'a member'} in the ecology`,
|
text: `Connect with ${item.name || 'a member'} on the board`,
|
||||||
action: '/ecology',
|
action: '/board',
|
||||||
actionText: 'Explore ecology',
|
actionText: 'Explore board',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (category === 'wiki') {
|
if (category === 'wiki') {
|
||||||
|
|
@ -144,14 +144,14 @@ export function useOnboarding(options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchRecommendations() {
|
async function fetchRecommendations() {
|
||||||
const [events, ecology, wiki] = await Promise.allSettled([
|
const [events, board, wiki] = await Promise.allSettled([
|
||||||
$fetch('/api/events/recommended'),
|
$fetch('/api/events/recommended'),
|
||||||
$fetch('/api/ecology/suggestions'),
|
$fetch('/api/board/suggestions'),
|
||||||
$fetch('/api/wiki/recommended'),
|
$fetch('/api/wiki/recommended'),
|
||||||
])
|
])
|
||||||
recommendations.value = {
|
recommendations.value = {
|
||||||
events: events.status === 'fulfilled' ? (events.value || []) : [],
|
events: events.status === 'fulfilled' ? (events.value || []) : [],
|
||||||
ecology: ecology.status === 'fulfilled' ? (ecology.value?.suggestions || []) : [],
|
board: board.status === 'fulfilled' ? (board.value?.suggestions || []) : [],
|
||||||
wiki: wiki.status === 'fulfilled' ? (wiki.value || []) : [],
|
wiki: wiki.status === 'fulfilled' ? (wiki.value || []) : [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,13 +351,13 @@ function statusClass(status) {
|
||||||
const hasProfileTags = computed(() => {
|
const hasProfileTags = computed(() => {
|
||||||
const m = member.value
|
const m = member.value
|
||||||
if (!m) return false
|
if (!m) return false
|
||||||
return m.craftTags?.length > 0 && m.communityEcology?.topics?.length > 0
|
return m.craftTags?.length > 0 && m.board?.topics?.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
const hasEcologyEngaged = computed(() => {
|
const hasEcologyEngaged = computed(() => {
|
||||||
const m = member.value
|
const m = member.value
|
||||||
if (!m) return false
|
if (!m) return false
|
||||||
return m.onboarding?.ecologyPageVisited && m.communityEcology?.topics?.some(
|
return m.onboarding?.boardPageVisited && m.board?.topics?.some(
|
||||||
t => ['help', 'interested', 'seeking'].includes(t.state)
|
t => ['help', 'interested', 'seeking'].includes(t.state)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({ middleware: "auth" });
|
await navigateTo("/board", { replace: true });
|
||||||
await navigateTo("/members?view=ecology", { replace: true });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({ middleware: "auth" });
|
await navigateTo("/board", { replace: true });
|
||||||
await navigateTo("/members?view=ecology", { replace: true });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -120,16 +120,16 @@
|
||||||
<div class="content-block">
|
<div class="content-block">
|
||||||
<div class="section-label">Quick Actions</div>
|
<div class="section-label">Quick Actions</div>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="/ecology"
|
to="/board"
|
||||||
class="quick-action"
|
class="quick-action"
|
||||||
:class="{ disabled: !canPeerSupport }"
|
:class="{ disabled: !canPeerSupport }"
|
||||||
:title="
|
:title="
|
||||||
!canPeerSupport
|
!canPeerSupport
|
||||||
? 'Complete your membership to access community ecology'
|
? 'Complete your membership to access the board'
|
||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Community ecology<span class="arrow">→</span>
|
Board<span class="arrow">→</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="/member/profile" class="quick-action">
|
<NuxtLink to="/member/profile" class="quick-action">
|
||||||
Update your profile<span class="arrow">→</span>
|
Update your profile<span class="arrow">→</span>
|
||||||
|
|
@ -198,8 +198,8 @@
|
||||||
Connect with other members through shared interests and
|
Connect with other members through shared interests and
|
||||||
cooperative topics.
|
cooperative topics.
|
||||||
</p>
|
</p>
|
||||||
<NuxtLink to="/ecology" class="section-link">
|
<NuxtLink to="/board" class="section-link">
|
||||||
Browse community ecology →
|
Browse the board →
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</DashedBox>
|
</DashedBox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -162,34 +162,34 @@
|
||||||
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<div class="section-label">Community Ecology</div>
|
<div class="section-label">Board</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Topics</label>
|
<label>Topics</label>
|
||||||
<CooperativeTagSelector
|
<CooperativeTagSelector
|
||||||
v-model="formData.communityEcologyTopics"
|
v-model="formData.boardTopics"
|
||||||
:tags="cooperativeTags"
|
:tags="cooperativeTags"
|
||||||
@suggest="openTagSuggest('cooperative')"
|
@suggest="openTagSuggest('cooperative')"
|
||||||
/>
|
/>
|
||||||
<PrivacyToggle v-model="formData.communityEcologyPrivacy" />
|
<PrivacyToggle v-model="formData.boardPrivacy" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Details</label>
|
<label>Details</label>
|
||||||
<textarea
|
<textarea
|
||||||
v-model="formData.communityEcologyDetails"
|
v-model="formData.boardDetails"
|
||||||
rows="3"
|
rows="3"
|
||||||
placeholder="What are you hoping to connect about?"
|
placeholder="What are you hoping to connect about?"
|
||||||
maxlength="300"
|
maxlength="300"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="char-count">
|
<div class="char-count">
|
||||||
{{ formData.communityEcologyDetails?.length || 0 }} / 300
|
{{ formData.boardDetails?.length || 0 }} / 300
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="toggle-field">
|
<div class="toggle-field">
|
||||||
<USwitch
|
<USwitch
|
||||||
v-model="formData.communityEcologyOfferPeerSupport"
|
v-model="formData.boardOfferPeerSupport"
|
||||||
aria-label="Offer Peer Support"
|
aria-label="Offer Peer Support"
|
||||||
/>
|
/>
|
||||||
<div class="toggle-label">
|
<div class="toggle-label">
|
||||||
|
|
@ -200,11 +200,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="formData.communityEcologyOfferPeerSupport" class="connections-panel">
|
<div v-if="formData.boardOfferPeerSupport" class="connections-panel">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Availability</label>
|
<label>Availability</label>
|
||||||
<textarea
|
<textarea
|
||||||
v-model="formData.communityEcologyAvailability"
|
v-model="formData.boardAvailability"
|
||||||
rows="3"
|
rows="3"
|
||||||
placeholder="e.g. Weekday afternoons ET"
|
placeholder="e.g. Weekday afternoons ET"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
|
@ -213,7 +213,7 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Slack Handle</label>
|
<label>Slack Handle</label>
|
||||||
<input
|
<input
|
||||||
v-model="formData.communityEcologySlackHandle"
|
v-model="formData.boardSlackHandle"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="@yourslackname"
|
placeholder="@yourslackname"
|
||||||
/>
|
/>
|
||||||
|
|
@ -222,13 +222,13 @@
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Personal Message</label>
|
<label>Personal Message</label>
|
||||||
<textarea
|
<textarea
|
||||||
v-model="formData.communityEcologyPersonalMessage"
|
v-model="formData.boardPersonalMessage"
|
||||||
rows="3"
|
rows="3"
|
||||||
maxlength="200"
|
maxlength="200"
|
||||||
placeholder="Brief note shown alongside your Slack handle"
|
placeholder="Brief note shown alongside your Slack handle"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="char-count">
|
<div class="char-count">
|
||||||
{{ formData.communityEcologyPersonalMessage?.length || 0 }} / 200
|
{{ formData.boardPersonalMessage?.length || 0 }} / 200
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -339,13 +339,13 @@ const formData = reactive({
|
||||||
showInDirectory: true,
|
showInDirectory: true,
|
||||||
craftTags: [],
|
craftTags: [],
|
||||||
craftTagsPrivacy: "members",
|
craftTagsPrivacy: "members",
|
||||||
communityEcologyTopics: [],
|
boardTopics: [],
|
||||||
communityEcologyPrivacy: "members",
|
boardPrivacy: "members",
|
||||||
communityEcologyDetails: "",
|
boardDetails: "",
|
||||||
communityEcologyOfferPeerSupport: false,
|
boardOfferPeerSupport: false,
|
||||||
communityEcologyAvailability: "",
|
boardAvailability: "",
|
||||||
communityEcologySlackHandle: "",
|
boardSlackHandle: "",
|
||||||
communityEcologyPersonalMessage: "",
|
boardPersonalMessage: "",
|
||||||
pronounsPrivacy: "members",
|
pronounsPrivacy: "members",
|
||||||
timeZonePrivacy: "members",
|
timeZonePrivacy: "members",
|
||||||
avatarPrivacy: "members",
|
avatarPrivacy: "members",
|
||||||
|
|
@ -387,13 +387,13 @@ const loadProfile = () => {
|
||||||
? [...memberData.value.craftTags]
|
? [...memberData.value.craftTags]
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const ecology = memberData.value.communityEcology || {};
|
const board = memberData.value.board || {};
|
||||||
formData.communityEcologyTopics = Array.isArray(ecology.topics) ? [...ecology.topics] : [];
|
formData.boardTopics = Array.isArray(board.topics) ? [...board.topics] : [];
|
||||||
formData.communityEcologyOfferPeerSupport = ecology.offerPeerSupport ?? false;
|
formData.boardOfferPeerSupport = board.offerPeerSupport ?? false;
|
||||||
formData.communityEcologyAvailability = ecology.availability || "";
|
formData.boardAvailability = board.availability || "";
|
||||||
formData.communityEcologySlackHandle = ecology.slackHandle || "";
|
formData.boardSlackHandle = board.slackHandle || "";
|
||||||
formData.communityEcologyPersonalMessage = ecology.personalMessage || "";
|
formData.boardPersonalMessage = board.personalMessage || "";
|
||||||
formData.communityEcologyDetails = ecology.details || "";
|
formData.boardDetails = board.details || "";
|
||||||
|
|
||||||
const privacy = memberData.value.privacy || {};
|
const privacy = memberData.value.privacy || {};
|
||||||
formData.pronounsPrivacy = privacy.pronouns || "members";
|
formData.pronounsPrivacy = privacy.pronouns || "members";
|
||||||
|
|
@ -403,7 +403,7 @@ const loadProfile = () => {
|
||||||
formData.bioPrivacy = privacy.bio || "members";
|
formData.bioPrivacy = privacy.bio || "members";
|
||||||
formData.locationPrivacy = privacy.location || "members";
|
formData.locationPrivacy = privacy.location || "members";
|
||||||
formData.craftTagsPrivacy = privacy.craftTags || "members";
|
formData.craftTagsPrivacy = privacy.craftTags || "members";
|
||||||
formData.communityEcologyPrivacy = privacy.communityEcology || "members";
|
formData.boardPrivacy = privacy.board || "members";
|
||||||
|
|
||||||
const notifs = memberData.value.notifications || {};
|
const notifs = memberData.value.notifications || {};
|
||||||
formData.notifications.events = notifs.events ?? true;
|
formData.notifications.events = notifs.events ?? true;
|
||||||
|
|
@ -423,15 +423,15 @@ const handleSubmit = async () => {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
body: { ...formData },
|
body: { ...formData },
|
||||||
}),
|
}),
|
||||||
$fetch("/api/members/me/community-ecology", {
|
$fetch("/api/members/me/board", {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
body: {
|
body: {
|
||||||
topics: formData.communityEcologyTopics,
|
topics: formData.boardTopics,
|
||||||
offerPeerSupport: formData.communityEcologyOfferPeerSupport,
|
offerPeerSupport: formData.boardOfferPeerSupport,
|
||||||
availability: formData.communityEcologyAvailability,
|
availability: formData.boardAvailability,
|
||||||
slackHandle: formData.communityEcologySlackHandle,
|
slackHandle: formData.boardSlackHandle,
|
||||||
personalMessage: formData.communityEcologyPersonalMessage,
|
personalMessage: formData.boardPersonalMessage,
|
||||||
details: formData.communityEcologyDetails,
|
details: formData.boardDetails,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,9 @@
|
||||||
<div class="profile-bio" v-html="renderMarkdown(member.bio)"></div>
|
<div class="profile-bio" v-html="renderMarkdown(member.bio)"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Two-column: Craft Tags + Community Ecology -->
|
<!-- Two-column: Craft Tags + Board -->
|
||||||
<div
|
<div
|
||||||
v-if="craftTagsDisplay.length > 0 || ecologyTopics.length > 0 || member.communityEcology?.details"
|
v-if="craftTagsDisplay.length > 0 || ecologyTopics.length > 0 || member.board?.details"
|
||||||
class="profile-two-col"
|
class="profile-two-col"
|
||||||
>
|
>
|
||||||
<!-- Left: What I Do -->
|
<!-- Left: What I Do -->
|
||||||
|
|
@ -125,9 +125,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right: Community Ecology -->
|
<!-- Right: Board -->
|
||||||
<div class="profile-section">
|
<div class="profile-section">
|
||||||
<div class="section-label">Community Ecology</div>
|
<div class="section-label">Board</div>
|
||||||
<div v-if="ecologyTopics.length > 0" class="tag-list">
|
<div v-if="ecologyTopics.length > 0" class="tag-list">
|
||||||
<span
|
<span
|
||||||
v-for="topic in ecologyTopics"
|
v-for="topic in ecologyTopics"
|
||||||
|
|
@ -138,24 +138,24 @@
|
||||||
{{ tagLabel('cooperative', topic.tagSlug) }}
|
{{ tagLabel('cooperative', topic.tagSlug) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="member.communityEcology?.details" class="profile-detail connection-details">
|
<p v-if="member.board?.details" class="profile-detail connection-details">
|
||||||
{{ member.communityEcology.details }}
|
{{ member.board.details }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Peer Support -->
|
<!-- Peer Support -->
|
||||||
<div v-if="member.communityEcology?.offerPeerSupport" class="profile-section">
|
<div v-if="member.board?.offerPeerSupport" class="profile-section">
|
||||||
<div class="section-label">Peer Support</div>
|
<div class="section-label">Peer Support</div>
|
||||||
<div class="dashed-box no-hover">
|
<div class="dashed-box no-hover">
|
||||||
<p v-if="member.communityEcology?.personalMessage" class="profile-detail">
|
<p v-if="member.board?.personalMessage" class="profile-detail">
|
||||||
{{ member.communityEcology.personalMessage }}
|
{{ member.board.personalMessage }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="member.communityEcology?.availability" class="profile-detail peer-availability">
|
<p v-if="member.board?.availability" class="profile-detail peer-availability">
|
||||||
{{ member.communityEcology.availability }}
|
{{ member.board.availability }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="member.communityEcology?.slackHandle" class="profile-detail peer-availability">
|
<p v-if="member.board?.slackHandle" class="profile-detail peer-availability">
|
||||||
Reach out on Slack: <span class="slack-handle">@{{ member.communityEcology.slackHandle }}</span>
|
Reach out on Slack: <span class="slack-handle">@{{ member.board.slackHandle }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -275,7 +275,7 @@ const tagLabel = (pool, slug) => {
|
||||||
const craftTagsDisplay = computed(() => member.value?.craftTags || []);
|
const craftTagsDisplay = computed(() => member.value?.craftTags || []);
|
||||||
|
|
||||||
const ecologyTopics = computed(
|
const ecologyTopics = computed(
|
||||||
() => member.value?.communityEcology?.topics || [],
|
() => member.value?.board?.topics || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Whether the member has any social links (for hero layout)
|
// Whether the member has any social links (for hero layout)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue