diff --git a/components/ExportOptions.vue b/components/ExportOptions.vue index e5a7ef6..b231825 100644 --- a/components/ExportOptions.vue +++ b/components/ExportOptions.vue @@ -424,7 +424,8 @@ const formatObjectAsMarkdown = (obj: any): string => { // Membership Agreement formatting - Complete document with all static and dynamic content const formatMembershipAgreementAsText = (data: any): string => { const formData = data.formData || {}; - let content = `MEMBERSHIP AGREEMENT\n====================\n\n`; + const cooperativeName = data.cooperativeName || formData.cooperativeName || "the cooperative"; + let content = ""; // Section 1: Who We Are content += `1. WHO WE ARE\n-------------\n\n`; @@ -459,18 +460,25 @@ const formatMembershipAgreementAsText = (data: any): string => { content += `New members join through a consent process, which means existing members must agree that adding this person won't harm the cooperative.\n\n`; content += `1. Trial period of ${formData.trialPeriodMonths || 3} months working together\n`; content += `2. Values alignment conversation\n`; - content += `3. Consent decision by current members\n`; - content += `4. Optional - Equal buy-in contribution of $${formData.buyInAmount || "[amount]"} (can be paid over time or waived based on need)\n\n`; + content += `3. Optional - Equal buy-in contribution of $${formData.buyInAmount || "[amount]"} (can be paid over time or waived based on need)\n\n`; content += `Leaving the Cooperative:\n`; - content += `Members can leave anytime with ${formData.noticeDays || 30} days notice. The cooperative will:\n\n`; + content += `Members can leave anytime with ${formData.noticeDays || 30} days notice. ${cooperativeName} will:\n\n`; content += `• Pay out their share of any surplus within ${formData.surplusPayoutDays || 30} days\n`; content += `• Return their buy-in contribution within ${formData.buyInReturnDays || 90} days\n`; content += `• Maintain respectful ongoing relationships when possible\n\n`; // Section 3: How We Make Decisions content += `3. HOW WE MAKE DECISIONS\n------------------------\n\n`; - content += `Consent-Based Decisions:\nWe use consent, not consensus. This means we move forward when no one has a principled objection that would harm the cooperative. An objection must explain how the proposal would contradict our values or threaten our sustainability.\n\n`; + + content += `Primary Decision Framework: ${data.decisionFrameworkName || "Consent-Based - No one objects strongly enough to block"}\n\n`; + + const frameworkDetails = data.decisionFrameworkDetails || {}; + if (frameworkDetails.practicalDescription) { + content += `${frameworkDetails.practicalDescription}\n\n`; + } else { + content += `We use consent, not consensus. This means we move forward when no one has a principled objection that would harm our organization. An objection must explain how the proposal would contradict our values or threaten our sustainability.\n\n`; + } content += `Day-to-Day Decisions:\nDecisions under $${formData.dayToDayLimit || 100} can be made by any member. Just tell others what you did at the next meeting.\n\n`; @@ -481,7 +489,7 @@ const formatMembershipAgreementAsText = (data: any): string => { content += `• Changing this agreement\n`; content += `• Taking on debt over $${formData.majorDebtThreshold || 5000}\n`; content += `• Fundamental changes to our purpose or structure\n`; - content += `• Dissolution of the cooperative\n\n`; + content += `• Dissolution of ${cooperativeName}\n\n`; content += `Meeting Structure:\n`; content += `• Regular meetings happen ${formData.meetingFrequency || "weekly"}\n`; @@ -491,12 +499,12 @@ const formatMembershipAgreementAsText = (data: any): string => { // Section 4: Money and Labour content += `4. MONEY AND LABOUR\n-------------------\n\n`; - content += `Equal Ownership:\nEach member owns an equal share of the cooperative, regardless of hours worked or tenure.\n\n`; + content += `Equal Ownership:\nEach member owns an equal share of ${cooperativeName}, regardless of hours worked or tenure.\n\n`; content += `Paying Ourselves:\n`; const payPolicy = formData.payPolicy || "equal-pay"; const payPolicyName = payPolicy.replace('-', ' ').replace(/\b\w/g, (l: string) => l.toUpperCase()); - content += `Pay Policy: ${payPolicyName}\n\n`; + content += `Pay Policy: ${data.payPolicyName || payPolicyName}\n\n`; if (payPolicy === 'equal-pay') { content += `All members receive equal compensation regardless of role or hours worked.\n`; @@ -516,7 +524,7 @@ const formatMembershipAgreementAsText = (data: any): string => { } content += `\nPayment Schedule:\n`; - content += `• Paid on the ${formData.paymentDay || 15} of each month\n`; + content += `• Paid on the ${data.paymentDayLabel || formData.paymentDay || 15} of each month\n`; content += `• Surplus (profit) distributed equally every ${formData.surplusFrequency || "quarter"}\n\n`; content += `Work Expectations:\n`; @@ -556,11 +564,13 @@ const formatMembershipAgreementAsText = (data: any): string => { // Section 7: Changing This Agreement content += `7. CHANGING THIS AGREEMENT\n--------------------------\n\n`; - content += `This is a living document. We review it every ${formData.reviewFrequency || "year"} and update it through our consent process. Small clarifications can happen anytime; structural changes need full member consent.\n\n`; + const frameworkLabel = data.decisionFrameworkLabel || "consent-based decision"; + const structuralReq = data.structuralChangeRequirement || "full member consent"; + content += `This is a living document. We review it every ${formData.reviewFrequency || "year"} and update it through our ${frameworkLabel} process. Small clarifications can happen anytime; structural changes need ${structuralReq}.\n\n`; // Section 8: If We Need to Close content += `8. IF WE NEED TO CLOSE\n----------------------\n\n`; - content += `If the cooperative dissolves:\n`; + content += `If ${cooperativeName} dissolves:\n`; content += `1. Pay all debts and obligations\n`; content += `2. Return member contributions\n`; content += `3. Distribute remaining assets equally among members\n`; @@ -569,19 +579,26 @@ const formatMembershipAgreementAsText = (data: any): string => { } content += `\n`; - // Section 9: Legal Bits - content += `9. LEGAL BITS\n-------------\n\n`; - content += `Legal Structure: ${formData.legalStructure || "[Cooperative corporation, LLC, partnership, etc.]"}\n`; - content += `Registered in: ${formData.registeredLocation || "[State/Province]"}\n`; - content += `Fiscal Year-End: ${formData.fiscalYearEndMonth || "December"} ${formData.fiscalYearEndDay || 31}\n\n`; - content += `This agreement works alongside but doesn't replace our legal incorporation documents. Where they conflict, we follow the law but work to align our legal structure with our values.\n\n`; + // Section 9: Legal Registration + content += `9. LEGAL REGISTRATION\n---------------------\n\n`; + + if (formData.isLegallyRegistered) { + content += `Legal Structure: ${formData.legalStructure || "[Cooperative corporation, LLC, partnership, etc.]"}\n`; + content += `Registered in: ${formData.registeredLocation || "[State/Province]"}\n`; + content += `Fiscal Year-End: ${formData.fiscalYearEndMonth || "December"} ${formData.fiscalYearEndDay || 31}\n\n`; + content += `This agreement works alongside but doesn't replace our legal incorporation documents. Where they conflict, we follow the law but work to align our legal structure with our values.\n\n`; + } else { + const thisCooperative = cooperativeName === "the cooperative" ? "This cooperative" : cooperativeName; + content += `${thisCooperative} operates as an informal collective. If we decide to register legally in the future, we'll update this section with our legal structure details.\n\n`; + } return content; }; const formatMembershipAgreementAsMarkdown = (data: any): string => { const formData = data.formData || {}; - let content = `# Membership Agreement\n\n`; + const cooperativeName = data.cooperativeName || formData.cooperativeName || "the cooperative"; + let content = ""; // Section 1: Who We Are content += `## 1. Who We Are\n\n`; @@ -616,19 +633,26 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { content += `New members join through a consent process, which means existing members must agree that adding this person won't harm the cooperative.\n\n`; content += `1. Trial period of **${formData.trialPeriodMonths || 3} months** working together\n`; content += `2. Values alignment conversation\n`; - content += `3. Consent decision by current members\n`; - content += `4. Optional - Equal buy-in contribution of **$${formData.buyInAmount || "[amount]"}** (can be paid over time or waived based on need)\n\n`; + content += `3. Optional - Equal buy-in contribution of **$${formData.buyInAmount || "[amount]"}** (can be paid over time or waived based on need)\n\n`; content += `### Leaving the Cooperative\n\n`; - content += `Members can leave anytime with **${formData.noticeDays || 30} days** notice. The cooperative will:\n\n`; + content += `Members can leave anytime with **${formData.noticeDays || 30} days** notice. ${cooperativeName} will:\n\n`; content += `- Pay out their share of any surplus within **${formData.surplusPayoutDays || 30} days**\n`; content += `- Return their buy-in contribution within **${formData.buyInReturnDays || 90} days**\n`; content += `- Maintain respectful ongoing relationships when possible\n\n`; // Section 3: How We Make Decisions content += `## 3. How We Make Decisions\n\n`; - content += `### Consent-Based Decisions\n\n`; - content += `We use consent, not consensus. This means we move forward when no one has a principled objection that would harm the cooperative. An objection must explain how the proposal would contradict our values or threaten our sustainability.\n\n`; + + content += `### Primary Decision Framework\n\n`; + content += `**${data.decisionFrameworkName || "Consent-Based - No one objects strongly enough to block"}**\n\n`; + + const frameworkDetails = data.decisionFrameworkDetails || {}; + if (frameworkDetails.practicalDescription) { + content += `${frameworkDetails.practicalDescription}\n\n`; + } else { + content += `We use consent, not consensus. This means we move forward when no one has a principled objection that would harm our organization. An objection must explain how the proposal would contradict our values or threaten our sustainability.\n\n`; + } content += `### Day-to-Day Decisions\n\n`; content += `Decisions under **$${formData.dayToDayLimit || 100}** can be made by any member. Just tell others what you did at the next meeting.\n\n`; @@ -642,7 +666,7 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { content += `- Changing this agreement\n`; content += `- Taking on debt over **$${formData.majorDebtThreshold || 5000}**\n`; content += `- Fundamental changes to our purpose or structure\n`; - content += `- Dissolution of the cooperative\n\n`; + content += `- Dissolution of ${cooperativeName}\n\n`; content += `### Meeting Structure\n\n`; content += `- Regular meetings happen **${formData.meetingFrequency || "weekly"}**\n`; @@ -653,12 +677,12 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { // Section 4: Money and Labour content += `## 4. Money and Labour\n\n`; content += `### Equal Ownership\n\n`; - content += `Each member owns an equal share of the cooperative, regardless of hours worked or tenure.\n\n`; + content += `Each member owns an equal share of ${cooperativeName}, regardless of hours worked or tenure.\n\n`; content += `### Paying Ourselves\n\n`; const payPolicy = formData.payPolicy || "equal-pay"; const payPolicyName = payPolicy.replace('-', ' ').replace(/\b\w/g, (l: string) => l.toUpperCase()); - content += `**Pay Policy:** ${payPolicyName}\n\n`; + content += `**Pay Policy:** ${data.payPolicyName || payPolicyName}\n\n`; if (payPolicy === 'equal-pay') { content += `All members receive equal compensation regardless of role or hours worked.\n\n`; @@ -678,7 +702,7 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { } content += `\n**Payment Schedule:**\n\n`; - content += `- Paid on the **${formData.paymentDay || 15}** of each month\n`; + content += `- Paid on the **${data.paymentDayLabel || formData.paymentDay || 15}** of each month\n`; content += `- Surplus (profit) distributed equally every **${formData.surplusFrequency || "quarter"}**\n\n`; content += `### Work Expectations\n\n`; @@ -718,11 +742,13 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { // Section 7: Changing This Agreement content += `## 7. Changing This Agreement\n\n`; - content += `This is a living document. We review it every **${formData.reviewFrequency || "year"}** and update it through our consent process. Small clarifications can happen anytime; structural changes need full member consent.\n\n`; + const frameworkLabel = data.decisionFrameworkLabel || "consent-based decision"; + const structuralReq = data.structuralChangeRequirement || "full member consent"; + content += `This is a living document. We review it every **${formData.reviewFrequency || "year"}** and update it through our ${frameworkLabel} process. Small clarifications can happen anytime; structural changes need ${structuralReq}.\n\n`; // Section 8: If We Need to Close content += `## 8. If We Need to Close\n\n`; - content += `If the cooperative dissolves:\n\n`; + content += `If ${cooperativeName} dissolves:\n\n`; content += `1. Pay all debts and obligations\n`; content += `2. Return member contributions\n`; content += `3. Distribute remaining assets equally among members\n`; @@ -731,12 +757,18 @@ const formatMembershipAgreementAsMarkdown = (data: any): string => { } content += `\n`; - // Section 9: Legal Bits - content += `## 9. Legal Bits\n\n`; - content += `- **Legal Structure:** ${formData.legalStructure || "[Cooperative corporation, LLC, partnership, etc.]"}\n`; - content += `- **Registered in:** ${formData.registeredLocation || "[State/Province]"}\n`; - content += `- **Fiscal Year-End:** ${formData.fiscalYearEndMonth || "December"} ${formData.fiscalYearEndDay || 31}\n\n`; - content += `This agreement works alongside but doesn't replace our legal incorporation documents. Where they conflict, we follow the law but work to align our legal structure with our values.\n\n`; + // Section 9: Legal Registration + content += `## 9. Legal Registration\n\n`; + + if (formData.isLegallyRegistered) { + content += `- **Legal Structure:** ${formData.legalStructure || "[Cooperative corporation, LLC, partnership, etc.]"}\n`; + content += `- **Registered in:** ${formData.registeredLocation || "[State/Province]"}\n`; + content += `- **Fiscal Year-End:** ${formData.fiscalYearEndMonth || "December"} ${formData.fiscalYearEndDay || 31}\n\n`; + content += `This agreement works alongside but doesn't replace our legal incorporation documents. Where they conflict, we follow the law but work to align our legal structure with our values.\n\n`; + } else { + const thisCooperative = cooperativeName === "the cooperative" ? "This cooperative" : cooperativeName; + content += `${thisCooperative} operates as an informal collective. If we decide to register legally in the future, we'll update this section with our legal structure details.\n\n`; + } return content; }; diff --git a/composables/useCoopInfo.ts b/composables/useCoopInfo.ts new file mode 100644 index 0000000..f6bf90d --- /dev/null +++ b/composables/useCoopInfo.ts @@ -0,0 +1,81 @@ +import { ref, watch, readonly } from 'vue' + +export interface CoopInfo { + cooperativeName: string + dateEstablished: string + purpose: string + coreValues: string + legalStructure: string + registeredLocation: string + isLegallyRegistered: boolean +} + +const STORAGE_KEY = 'coop-info' + +// Global reactive state +const coopInfo = ref({ + cooperativeName: '', + dateEstablished: '', + purpose: '', + coreValues: '', + legalStructure: '', + registeredLocation: '', + isLegallyRegistered: false +}) + +// Flag to prevent loading during initial save +let isInitialized = false + +export const useCoopInfo = () => { + + // Load data from localStorage on first use + if (!isInitialized && process.client) { + const saved = localStorage.getItem(STORAGE_KEY) + if (saved) { + try { + const parsedData = JSON.parse(saved) + coopInfo.value = { ...coopInfo.value, ...parsedData } + } catch (error) { + console.error('Error loading coop info:', error) + } + } + isInitialized = true + + // Set up watcher to save changes + watch( + coopInfo, + (newData) => { + localStorage.setItem(STORAGE_KEY, JSON.stringify(newData)) + }, + { deep: true } + ) + } + + // Helper function to update specific fields + const updateCoopInfo = (updates: Partial) => { + coopInfo.value = { ...coopInfo.value, ...updates } + } + + // Helper function to get display name (with fallback) + const getDisplayName = () => { + return coopInfo.value.cooperativeName || 'Worker Cooperative' + } + + // Helper function to get organization name for different contexts + const getOrgName = () => { + return coopInfo.value.cooperativeName || 'Organization' + } + + // Helper function to check if basic info is complete + const isBasicInfoComplete = () => { + return !!(coopInfo.value.cooperativeName && coopInfo.value.cooperativeName.trim()) + } + + return { + coopInfo: readonly(coopInfo), + updateCoopInfo, + getDisplayName, + getOrgName, + isBasicInfoComplete + } +} \ No newline at end of file diff --git a/pages/coach/skills-to-offers.vue b/pages/coach/skills-to-offers.vue deleted file mode 100644 index 8a386db..0000000 --- a/pages/coach/skills-to-offers.vue +++ /dev/null @@ -1,596 +0,0 @@ - - - \ No newline at end of file diff --git a/pages/templates/conflict-resolution-framework.vue b/pages/templates/conflict-resolution-framework.vue index a6bff90..8dd28e4 100644 --- a/pages/templates/conflict-resolution-framework.vue +++ b/pages/templates/conflict-resolution-framework.vue @@ -16,7 +16,7 @@

+ :data-org-name="getOrgName()"> CONFLICT RESOLUTION

@@ -895,6 +895,9 @@