feat: add initial application structure with configuration, UI components, and state management
This commit is contained in:
parent
fadf94002c
commit
0af6b17792
56 changed files with 6137 additions and 129 deletions
117
stores/streams.ts
Normal file
117
stores/streams.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
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"],
|
||||
},
|
||||
}
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue