Huge bunch of UI/UX improvements and tweaks!
Some checks failed
Test / vitest (push) Successful in 10m36s
Test / playwright (push) Failing after 9m23s
Test / visual (push) Failing after 9m13s
Test / Notify on failure (push) Successful in 2s

This commit is contained in:
Jennie Robinson Faber 2026-04-06 16:17:12 +01:00
parent 501be10bfe
commit fb25e72215
37 changed files with 1651 additions and 949 deletions

View file

@ -26,8 +26,8 @@ export default defineEventHandler(async (event) => {
const results = []
for (const preReg of preRegs) {
// Only send to selected pre-registrants (skip already invited/accepted/expired)
if (preReg.status !== 'selected' && preReg.status !== 'pending') {
// Only send to pending/selected/invited (allow resend); skip accepted/expired
if (preReg.status !== 'selected' && preReg.status !== 'pending' && preReg.status !== 'invited') {
results.push({
preRegistrantId: preReg._id,
email: preReg.email,

View file

@ -2,6 +2,7 @@ import jwt from 'jsonwebtoken'
import PreRegistration from '../../models/preRegistration.js'
import Member from '../../models/member.js'
import { connectDB } from '../../utils/mongoose.js'
import { assignMemberNumber } from '../../utils/memberNumber.js'
export default defineEventHandler(async (event) => {
const body = await validateBody(event, inviteAcceptSchema)
@ -47,6 +48,8 @@ export default defineEventHandler(async (event) => {
status: body.contributionTier === '0' ? 'active' : 'pending_payment',
})
await assignMemberNumber(member._id)
// Update pre-registration
await PreRegistration.findByIdAndUpdate(preReg._id, {
$set: {

View file

@ -30,7 +30,7 @@ export default defineEventHandler(async (event) => {
status: "active",
})
.select(
"name pronouns timeZone avatar studio bio location socialLinks offering lookingFor privacy circle peerSupport craftTags communityConnections createdAt",
"name pronouns timeZone avatar studio bio location socialLinks offering lookingFor privacy circle peerSupport craftTags communityConnections createdAt memberNumber",
)
.lean();
@ -48,6 +48,7 @@ export default defineEventHandler(async (event) => {
name: member.name,
circle: member.circle,
createdAt: member.createdAt,
memberNumber: member.memberNumber,
};
// Helper function to check if field should be visible

View file

@ -5,6 +5,7 @@ import { getSlackService } from '../../utils/slack.ts'
import { validateBody } from '../../utils/validateBody.js'
import { memberCreateSchema } from '../../utils/schemas.js'
import { sendWelcomeEmail } from '../../utils/resend.js'
import { assignMemberNumber } from '../../utils/memberNumber.js'
// Simple payment check function to avoid import issues
const requiresPayment = (contributionValue) => contributionValue !== '0'
@ -101,6 +102,8 @@ export default defineEventHandler(async (event) => {
const member = new Member(validatedData)
await member.save()
await assignMemberNumber(member._id)
// Log member joined
logActivity(member._id, 'member_joined', {
circle: member.circle

8
server/models/counter.js Normal file
View file

@ -0,0 +1,8 @@
import mongoose from 'mongoose'
const counterSchema = new mongoose.Schema({
_id: String,
seq: { type: Number, default: 0 }
})
export default mongoose.models.Counter || mongoose.model('Counter', counterSchema)

View file

@ -181,6 +181,8 @@ const memberSchema = new mongoose.Schema({
// Session revocation via token versioning
tokenVersion: { type: Number, default: 0 },
memberNumber: { type: Number, unique: true, sparse: true },
createdAt: { type: Date, default: Date.now },
lastLogin: Date,
});

View file

@ -0,0 +1,12 @@
import Counter from '../models/counter.js'
import Member from '../models/member.js'
export async function assignMemberNumber(memberId) {
const counter = await Counter.findOneAndUpdate(
{ _id: 'memberNumber' },
{ $inc: { seq: 1 } },
{ new: true, upsert: true }
)
await Member.findByIdAndUpdate(memberId, { memberNumber: counter.seq }, { runValidators: false })
return counter.seq
}