feat: add Tag, TagSuggestion, Connection models and extend Member schema

Adds three new Mongoose models for the community connections feature. Extends
Member with craftTags, communityConnections block, privacy fields for both,
and a connectionRequests notification preference.
This commit is contained in:
Jennie Robinson Faber 2026-04-05 16:06:03 +01:00
parent 4aacb26c4b
commit 8112e5ea47
4 changed files with 72 additions and 0 deletions

View file

@ -0,0 +1,22 @@
import mongoose from 'mongoose'
const connectionSchema = new mongoose.Schema({
initiator: { type: mongoose.Schema.Types.ObjectId, ref: 'Member', required: true },
recipient: { type: mongoose.Schema.Types.ObjectId, ref: 'Member', required: true },
status: { type: String, enum: ['pending', 'confirmed'], default: 'pending' },
matchingTags: [
{
tagSlug: String,
initiatorState: String,
recipientState: String,
},
],
hiddenBy: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Member' }],
createdAt: { type: Date, default: Date.now },
confirmedAt: Date,
})
connectionSchema.index({ initiator: 1, recipient: 1 }, { unique: true })
connectionSchema.index({ recipient: 1, status: 1 })
export default mongoose.models.Connection || mongoose.model('Connection', connectionSchema)

View file

@ -90,6 +90,21 @@ const memberSchema = new mongoose.Schema({
slackDMChannelId: String, // DM channel ID for direct messaging
},
craftTags: [String],
communityConnections: {
topics: [
{
tagSlug: String,
state: { type: String, enum: ['help', 'interested', 'seeking'] },
},
],
offerPeerSupport: { type: Boolean, default: false },
availability: String,
slackHandle: String,
personalMessage: String,
details: String,
},
// Privacy settings for profile fields
privacy: {
pronouns: {
@ -137,12 +152,23 @@ const memberSchema = new mongoose.Schema({
enum: ["public", "members", "private"],
default: "members",
},
craftTags: {
type: String,
enum: ["public", "members", "private"],
default: "members",
},
communityConnections: {
type: String,
enum: ["public", "members", "private"],
default: "members",
},
},
notifications: {
events: { type: Boolean, default: true },
updates: { type: Boolean, default: true },
peerRequests: { type: Boolean, default: true },
connectionRequests: { type: Boolean, default: true },
},
inviteEmailSent: { type: Boolean, default: false },

13
server/models/tag.js Normal file
View file

@ -0,0 +1,13 @@
import mongoose from 'mongoose'
const tagSchema = new mongoose.Schema({
slug: { type: String, required: true, unique: true },
label: { type: String, required: true },
pool: { type: String, enum: ['craft', 'cooperative'], required: true },
active: { type: Boolean, default: true },
createdAt: { type: Date, default: Date.now },
})
tagSchema.index({ pool: 1, active: 1 })
export default mongoose.models.Tag || mongoose.model('Tag', tagSchema)

View file

@ -0,0 +1,11 @@
import mongoose from 'mongoose'
const tagSuggestionSchema = new mongoose.Schema({
label: { type: String, required: true },
pool: { type: String, enum: ['craft', 'cooperative'], required: true },
suggestedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'Member', required: true },
status: { type: String, enum: ['pending', 'approved', 'rejected'], default: 'pending' },
createdAt: { type: Date, default: Date.now },
})
export default mongoose.models.TagSuggestion || mongoose.model('TagSuggestion', tagSuggestionSchema)