app/components/WizardPoliciesStep.vue

168 lines
4.8 KiB
Vue

<template>
<div class="max-w-4xl mx-auto space-y-6">
<!-- Section Header -->
<div class="mb-8">
<h3 class="text-2xl font-black text-black mb-2">
How will you share money?
</h3>
<p class="text-neutral-600">
This is the foundation of your co-op's finances. Choose a pay approach
and set your hourly rate.
</p>
</div>
<!-- Pay Policy Selection -->
<div class="p-6 border-2 border-black rounded-xl bg-white shadow-md">
<h4 class="font-bold mb-2">Step 1: Choose your pay approach</h4>
<p class="text-sm text-gray-600 mb-4">
How should available money be shared among members?
</p>
<URadioGroup
v-model="selectedPolicy"
:items="policyOptions"
@update:model-value="updatePolicy"
variant="list"
size="xl"
class="flex flex-col gap-2 w-full" />
</div>
<!-- Hourly Wage Input -->
<div class="p-6 border-2 border-black rounded-xl bg-white shadow-md">
<h4 class="font-bold mb-2">Step 2: Set your base wage</h4>
<p class="text-sm text-gray-600 mb-4">
This hourly rate applies to all paid work in your co-op
</p>
<div class="flex gap-4 items-start">
<!-- Currency Selection -->
<UFormField label="Currency" class="w-1/2">
<USelect
v-model="selectedCurrency"
:items="currencySelectOptions"
placeholder="Select currency"
size="xl"
class="w-full"
@update:model-value="updateCurrency">
<template #leading>
<span class="text-lg">{{
getCurrencySymbol(selectedCurrency)
}}</span>
</template>
</USelect>
</UFormField>
<UFormField label="Hourly Rate" class="w-1/2">
<UInput
v-model="wageText"
type="text"
placeholder="0.00"
size="xl"
class="text-2xl font-bold w-full"
@update:model-value="validateAndSaveWage">
<template #leading>
<span class="text-neutral-500 text-xl">{{
getCurrencySymbol(selectedCurrency)
}}</span>
</template>
</UInput>
</UFormField>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { currencyOptions, getCurrencySymbol } from "~/utils/currency";
const emit = defineEmits<{
"save-status": [status: "saving" | "saved" | "error"];
}>();
// Store
const coop = useCoopBuilder();
const store = useCoopBuilderStore();
// Initialize from store
const selectedPolicy = ref(coop.policy.value?.relationship || "equal-pay");
const roleBands = ref(coop.policy.value?.roleBands || {});
const wageText = ref(String(store.equalHourlyWage || ""));
const selectedCurrency = ref(coop.currency.value || "EUR");
function parseNumberInput(val: unknown): number {
if (typeof val === "number") return val;
if (typeof val === "string") {
const cleaned = val.replace(/,/g, ".").replace(/[^0-9.\-]/g, "");
const parsed = parseFloat(cleaned);
return Number.isFinite(parsed) ? parsed : 0;
}
return 0;
}
// Simplified pay policy options
const policyOptions = [
{
value: "equal-pay",
label: "Equal pay - Everyone gets the same amount",
},
{
value: "hours-weighted",
label: "Hours-based - Pay proportional to hours worked",
},
{
value: "needs-weighted",
label: "Needs-based - Pay proportional to individual needs",
},
];
// Currency options for USelect (simplified format)
const currencySelectOptions = computed(() =>
currencyOptions.map((currency) => ({
label: `${currency.name} (${currency.code})`,
value: currency.code,
}))
);
// Already initialized above with store values
// Removed uniqueRoles computed - no longer needed with simplified policies
function updateCurrency(value: string) {
selectedCurrency.value = value;
coop.setCurrency(value);
emit("save-status", "saved");
}
function updatePolicy(value: string) {
coop.setPolicy(value as "equal-pay" | "needs-weighted" | "hours-weighted");
// Trigger payroll reallocation after policy change
const allocatedMembers = coop.allocatePayroll();
allocatedMembers.forEach((m) => {
coop.upsertMember(m);
});
emit("save-status", "saved");
}
// Removed updateRoleBands - no longer needed with simplified policies
// Text input for wage with validation (initialized above)
function validateAndSaveWage(value: string) {
const cleanValue = value.replace(/[^\d.]/g, "");
const numValue = parseFloat(cleanValue);
wageText.value = cleanValue;
if (!isNaN(numValue) && numValue >= 0) {
coop.setEqualWage(numValue);
// Trigger payroll reallocation after wage change
const allocatedMembers = coop.allocatePayroll();
allocatedMembers.forEach((m) => {
coop.upsertMember(m);
});
emit("save-status", "saved");
}
}
</script>