app/stores/streams.ts

118 lines
3.1 KiB
TypeScript

import { defineStore } from "pinia";
export const useStreamsStore = defineStore(
"streams",
() => {
// Schema version for persistence
const schemaVersion = "1.0";
// Revenue streams with all properties
const streams = ref([]);
// Computed totals
const totalTargetPct = computed(() =>
streams.value.reduce((sum, stream) => sum + (stream.targetPct || 0), 0)
);
const totalMonthlyAmount = computed(() =>
streams.value.reduce(
(sum, stream) => sum + (stream.targetMonthlyAmount || 0),
0
)
);
// Validation computed
const targetPctDeviation = computed(() => {
const total = totalTargetPct.value;
return Math.abs(100 - total);
});
const hasValidStreams = computed(() => {
return streams.value.every(
(stream) =>
stream.name &&
stream.category &&
stream.payoutDelayDays >= 0 &&
(stream.targetPct >= 0 || stream.targetMonthlyAmount >= 0)
);
});
// Wizard-required actions
function upsertStream(stream) {
const existingIndex = streams.value.findIndex((s) => s.id === stream.id);
if (existingIndex > -1) {
streams.value[existingIndex] = {
...streams.value[existingIndex],
...stream,
};
} else {
const newStream = {
id: stream.id || Date.now().toString(),
name: stream.name,
category: stream.category,
subcategory: stream.subcategory || "",
targetPct: stream.targetPct || 0,
targetMonthlyAmount: stream.targetMonthlyAmount || 0,
certainty: stream.certainty || "Aspirational", // Committed|Probable|Aspirational
payoutDelayDays: stream.payoutDelayDays || 0,
terms: stream.terms || "",
revenueSharePct: stream.revenueSharePct || 0,
platformFeePct: stream.platformFeePct || 0,
restrictions: stream.restrictions || "General", // Restricted|General
seasonalityWeights:
stream.seasonalityWeights || new Array(12).fill(1),
effortHoursPerMonth: stream.effortHoursPerMonth || 0,
...stream,
};
streams.value.push(newStream);
}
}
// Legacy actions
function addStream(stream) {
upsertStream(stream);
}
function updateStream(id, updates) {
const stream = streams.value.find((s) => s.id === id);
if (stream) {
Object.assign(stream, updates);
}
}
function removeStream(id) {
const index = streams.value.findIndex((s) => s.id === id);
if (index > -1) {
streams.value.splice(index, 1);
}
}
// Reset function
function resetStreams() {
streams.value = [];
}
return {
streams,
totalTargetPct,
totalMonthlyAmount,
targetPctDeviation,
hasValidStreams,
schemaVersion,
// Wizard actions
upsertStream,
resetStreams,
// Legacy actions
addStream,
updateStream,
removeStream,
};
},
{
persist: {
key: "urgent-tools-streams",
paths: ["streams"],
},
}
);