refactor: enhance routing and state management in CoopBuilder, add migration checks on startup, and update Tailwind configuration for improved component styling
This commit is contained in:
parent
848386e3dd
commit
4cea1f71fe
55 changed files with 4053 additions and 1486 deletions
|
|
@ -1,4 +1,6 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from 'vue';
|
||||
import { coverage, teamCoverageStats } from "~/types/members";
|
||||
|
||||
export const useMembersStore = defineStore(
|
||||
"members",
|
||||
|
|
@ -34,10 +36,16 @@ export const useMembersStore = defineStore(
|
|||
|
||||
// Normalize a member object to ensure required structure and sane defaults
|
||||
function normalizeMember(raw) {
|
||||
// Calculate hoursPerWeek from targetHours (monthly) if not explicitly set
|
||||
const targetHours = Number(raw.capacity?.targetHours) || 0;
|
||||
const hoursPerWeek = raw.hoursPerWeek ?? (targetHours > 0 ? targetHours / 4.33 : 0);
|
||||
|
||||
const normalized = {
|
||||
id: raw.id || Date.now().toString(),
|
||||
displayName: typeof raw.displayName === "string" ? raw.displayName : "",
|
||||
roleFocus: typeof raw.roleFocus === "string" ? raw.roleFocus : "",
|
||||
role: raw.role || raw.roleFocus || "",
|
||||
hoursPerWeek: hoursPerWeek,
|
||||
payRelationship: raw.payRelationship || "FullyPaid",
|
||||
capacity: {
|
||||
minHours: Number(raw.capacity?.minHours) || 0,
|
||||
|
|
@ -49,6 +57,11 @@ export const useMembersStore = defineStore(
|
|||
privacyNeeds: raw.privacyNeeds || "aggregate_ok",
|
||||
deferredHours: Number(raw.deferredHours ?? 0),
|
||||
quarterlyDeferredCap: Number(raw.quarterlyDeferredCap ?? 240),
|
||||
// NEW fields for needs coverage
|
||||
minMonthlyNeeds: Number(raw.minMonthlyNeeds) || 0,
|
||||
targetMonthlyPay: Number(raw.targetMonthlyPay) || 0,
|
||||
externalMonthlyIncome: Number(raw.externalMonthlyIncome) || 0,
|
||||
monthlyPayPlanned: Number(raw.monthlyPayPlanned) || 0,
|
||||
...raw,
|
||||
};
|
||||
return normalized;
|
||||
|
|
@ -187,6 +200,56 @@ export const useMembersStore = defineStore(
|
|||
members.value = [];
|
||||
}
|
||||
|
||||
// Coverage calculations for individual members
|
||||
function getMemberCoverage(memberId) {
|
||||
const member = members.value.find((m) => m.id === memberId);
|
||||
if (!member) return { minPct: undefined, targetPct: undefined };
|
||||
|
||||
return coverage(
|
||||
member.minMonthlyNeeds || 0,
|
||||
member.targetMonthlyPay || 0,
|
||||
member.monthlyPayPlanned || 0,
|
||||
member.externalMonthlyIncome || 0
|
||||
);
|
||||
}
|
||||
|
||||
// Team-wide coverage statistics
|
||||
const teamStats = computed(() => teamCoverageStats(members.value));
|
||||
|
||||
// Pay policy configuration
|
||||
const payPolicy = ref({
|
||||
relationship: 'equal-pay' as const,
|
||||
notes: '',
|
||||
equalBase: 0,
|
||||
needsWeight: 0.5,
|
||||
roleBands: {},
|
||||
hoursRate: 0,
|
||||
customFormula: ''
|
||||
});
|
||||
|
||||
// Setters for new fields
|
||||
function setMonthlyNeeds(memberId, minNeeds, targetPay) {
|
||||
const member = members.value.find((m) => m.id === memberId);
|
||||
if (member) {
|
||||
member.minMonthlyNeeds = Number(minNeeds) || 0;
|
||||
member.targetMonthlyPay = Number(targetPay) || 0;
|
||||
}
|
||||
}
|
||||
|
||||
function setExternalIncome(memberId, income) {
|
||||
const member = members.value.find((m) => m.id === memberId);
|
||||
if (member) {
|
||||
member.externalMonthlyIncome = Number(income) || 0;
|
||||
}
|
||||
}
|
||||
|
||||
function setPlannedPay(memberId, planned) {
|
||||
const member = members.value.find((m) => m.id === memberId);
|
||||
if (member) {
|
||||
member.monthlyPayPlanned = Number(planned) || 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
members,
|
||||
capacityTotals,
|
||||
|
|
@ -194,6 +257,8 @@ export const useMembersStore = defineStore(
|
|||
validationDetails,
|
||||
isValid,
|
||||
schemaVersion,
|
||||
payPolicy,
|
||||
teamStats,
|
||||
// Wizard actions
|
||||
upsertMember,
|
||||
setCapacity,
|
||||
|
|
@ -202,6 +267,11 @@ export const useMembersStore = defineStore(
|
|||
setExternalCoveragePct,
|
||||
setPrivacy,
|
||||
resetMembers,
|
||||
// New coverage actions
|
||||
setMonthlyNeeds,
|
||||
setExternalIncome,
|
||||
setPlannedPay,
|
||||
getMemberCoverage,
|
||||
// Legacy actions
|
||||
addMember,
|
||||
updateMember,
|
||||
|
|
@ -211,7 +281,7 @@ export const useMembersStore = defineStore(
|
|||
{
|
||||
persist: {
|
||||
key: "urgent-tools-members",
|
||||
paths: ["members", "privacyFlags"],
|
||||
paths: ["members", "privacyFlags", "payPolicy"],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue