style: enhance CSS for improved layout and responsiveness, integrate Ubuntu font, and streamline export options across templates
This commit is contained in:
parent
3b33ff3819
commit
eede87a273
6 changed files with 1130 additions and 1745 deletions
|
|
@ -3,10 +3,12 @@
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "@nuxt/ui";
|
@import "@nuxt/ui";
|
||||||
|
|
||||||
|
/* Ubuntu font import */
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&family=Ubuntu+Mono:wght@400;700&display=swap");
|
||||||
|
|
||||||
[data-theme="dark"] {
|
[data-theme="dark"] {
|
||||||
html { @apply bg-white text-neutral-900; }
|
html { @apply bg-white text-neutral-900; }
|
||||||
html.dark { @apply bg-neutral-950 text-neutral-100; }
|
html.dark { @apply bg-neutral-950 text-neutral-100; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable all animations, transitions, and smooth scrolling app-wide */
|
/* Disable all animations, transitions, and smooth scrolling app-wide */
|
||||||
|
|
@ -22,12 +24,347 @@ body {
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-page {
|
/* =========================
|
||||||
@apply max-w-4xl mx-auto relative p-8 border-1 border-neutral-900 dark:border-neutral-100;
|
TEMPLATE DOCUMENT LAYOUT
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
/* Template wrapper and document styling */
|
||||||
|
.template-wrapper {
|
||||||
|
@apply min-h-screen relative;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Bitmap aesthetic overrides - remove all rounded corners */
|
.document-page {
|
||||||
|
@apply max-w-full mx-auto relative p-8 border-1 border-neutral-900 dark:border-neutral-100;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
SECTION STYLING
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.section-card {
|
||||||
|
@apply border border-neutral-200 dark:border-neutral-800 rounded-lg p-5 mb-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-card::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
left: 4px;
|
||||||
|
right: -4px;
|
||||||
|
bottom: -4px;
|
||||||
|
background: black;
|
||||||
|
background-image: radial-gradient(white 1px, transparent 1px);
|
||||||
|
background-size: 2px 2px;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: inherit;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subsection-title {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
margin: 0 0 0.75rem 0;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
FORM STYLING
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.form-group-large {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-large > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure consistent alignment for all form fields */
|
||||||
|
.form-group-large :deep(textarea),
|
||||||
|
.form-group-large :deep(input),
|
||||||
|
.form-group-large :deep(select),
|
||||||
|
.form-group-large :deep(.ui-select),
|
||||||
|
.form-group-large :deep(.ui-input),
|
||||||
|
.form-group-large :deep(.ui-textarea) {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
padding-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Additional targeting for UInput, USelect, UTextarea components */
|
||||||
|
.form-group-large :deep(.u-input),
|
||||||
|
.form-group-large :deep(.u-select),
|
||||||
|
.form-group-large :deep(.u-textarea),
|
||||||
|
.form-group-large :deep([data-headlessui-state]),
|
||||||
|
.form-group-large :deep(.relative) {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-large :deep(.u-input input),
|
||||||
|
.form-group-large :deep(.u-select select),
|
||||||
|
.form-group-large :deep(.u-textarea textarea) {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
padding-left: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-large .large-field {
|
||||||
|
@apply block w-full mt-2 text-lg rounded-md border-none transition-colors duration-150 ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-large .large-field:focus {
|
||||||
|
background: #f3f4f6;
|
||||||
|
box-shadow: none;
|
||||||
|
outline: 2px solid #3b82f6;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-field {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
min-width: 120px;
|
||||||
|
border: none;
|
||||||
|
background: #f9fafb;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-field:focus {
|
||||||
|
background: #f3f4f6;
|
||||||
|
outline: 1px solid #3b82f6;
|
||||||
|
outline-offset: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-field {
|
||||||
|
min-width: 80px !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wide-field {
|
||||||
|
min-width: 250px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-block .block-field {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
border: none;
|
||||||
|
background: #f9fafb;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group-block .block-field:focus {
|
||||||
|
background: #f3f4f6;
|
||||||
|
outline: 1px solid #3b82f6;
|
||||||
|
outline-offset: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
CONTENT STYLING
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.content-paragraph {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
display: list-item;
|
||||||
|
list-style-position: outside;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list.numbered {
|
||||||
|
list-style-type: decimal;
|
||||||
|
counter-reset: list-counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list.numbered li {
|
||||||
|
list-style-type: decimal;
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list:not(.numbered) {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list:not(.numbered) li {
|
||||||
|
list-style-type: disc;
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure bullets are visible even with flex items */
|
||||||
|
.content-list li.flex {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list li .flex {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix flex list items to show bullets */
|
||||||
|
.content-list li[class*="flex"] {
|
||||||
|
display: list-item !important;
|
||||||
|
list-style-position: outside !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure numbered lists show numbers even with flex */
|
||||||
|
.content-list.numbered li[class*="flex"] {
|
||||||
|
list-style-type: decimal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure bullet lists show bullets even with flex */
|
||||||
|
.content-list:not(.numbered) li[class*="flex"] {
|
||||||
|
list-style-type: disc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
CHECKBOX AND VALUES GRID
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.checkbox-item {
|
||||||
|
@apply flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-group {
|
||||||
|
@apply flex flex-col space-y-3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
DITHERED SHADOW EFFECTS
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.dither-shadow {
|
||||||
|
background: black;
|
||||||
|
background-image: radial-gradient(white 1px, transparent 1px);
|
||||||
|
background-size: 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .dither-shadow {
|
||||||
|
background: white;
|
||||||
|
background-image: radial-gradient(black 1px, transparent 1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
BUTTON STYLING
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.export-btn {
|
||||||
|
@apply bg-white border border-black text-black font-mono uppercase font-normal tracking-wide;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
min-width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-btn:hover {
|
||||||
|
@apply bg-black text-white -translate-x-px -translate-y-px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-btn.primary {
|
||||||
|
@apply bg-black text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-btn.primary:hover {
|
||||||
|
@apply bg-black -translate-x-px -translate-y-px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-btn svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-btn.large svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode export buttons */
|
||||||
|
html.dark .export-btn {
|
||||||
|
@apply bg-neutral-950 border-white text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .export-btn:hover {
|
||||||
|
@apply bg-white text-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .export-btn.primary {
|
||||||
|
@apply bg-white text-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .export-btn.primary:hover {
|
||||||
|
@apply bg-white text-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General buttons with bitmap styling */
|
||||||
|
button:not(.export-btn) {
|
||||||
|
background: white !important;
|
||||||
|
border: 1px solid black !important;
|
||||||
|
color: black !important;
|
||||||
|
font-family: "Ubuntu Mono", monospace !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
letter-spacing: 0.5px !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(.export-btn):hover {
|
||||||
|
background: black !important;
|
||||||
|
color: white !important;
|
||||||
|
transform: translateY(-1px) translateX(-1px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode buttons */
|
||||||
|
html.dark button:not(.export-btn) {
|
||||||
|
background: #0a0a0a !important;
|
||||||
|
border: 1px solid white !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark button:not(.export-btn):hover {
|
||||||
|
background: white !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
BITMAP AESTHETIC OVERRIDES
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
/* Remove all rounded corners */
|
||||||
* {
|
* {
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
font-family: "Ubuntu", monospace !important;
|
font-family: "Ubuntu", monospace !important;
|
||||||
|
|
@ -37,6 +374,188 @@ body {
|
||||||
input,
|
input,
|
||||||
textarea,
|
textarea,
|
||||||
select {
|
select {
|
||||||
|
border: 1px solid black !important;
|
||||||
|
background: white !important;
|
||||||
|
color: black !important;
|
||||||
font-family: "Ubuntu Mono", monospace !important;
|
font-family: "Ubuntu Mono", monospace !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input:focus,
|
||||||
|
textarea:focus,
|
||||||
|
select:focus {
|
||||||
|
outline: 2px solid black !important;
|
||||||
|
outline-offset: -2px !important;
|
||||||
|
background: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode form fields */
|
||||||
|
html.dark input,
|
||||||
|
html.dark textarea,
|
||||||
|
html.dark select {
|
||||||
|
border: 1px solid white !important;
|
||||||
|
background: #0a0a0a !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark input:focus,
|
||||||
|
html.dark textarea:focus,
|
||||||
|
html.dark select:focus {
|
||||||
|
outline: 2px solid white !important;
|
||||||
|
background: #0a0a0a !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox and radio button styling */
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
border: 2px solid black !important;
|
||||||
|
background: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:checked,
|
||||||
|
input[type="radio"]:checked {
|
||||||
|
background: black !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark input[type="checkbox"],
|
||||||
|
html.dark input[type="radio"] {
|
||||||
|
border: 2px solid white !important;
|
||||||
|
background: #0a0a0a !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark input[type="checkbox"]:checked,
|
||||||
|
html.dark input[type="radio"]:checked {
|
||||||
|
background: white !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Document titles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-family: "Ubuntu", monospace !important;
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All text */
|
||||||
|
p,
|
||||||
|
span,
|
||||||
|
div {
|
||||||
|
color: inherit !important;
|
||||||
|
font-family: "Ubuntu", monospace !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
HIDE ELEMENTS FROM PRINT
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
.no-print,
|
||||||
|
.no-pdf {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
PRINT STYLES
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.no-print,
|
||||||
|
.no-pdf {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-wrapper {
|
||||||
|
background: white !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
min-height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-page {
|
||||||
|
max-width: none !important;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-page::before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
height: 0.5in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14pt;
|
||||||
|
page-break-after: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-card {
|
||||||
|
break-inside: avoid;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-item {
|
||||||
|
font-size: 10pt;
|
||||||
|
margin: 2pt 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-field,
|
||||||
|
.large-field,
|
||||||
|
.block-field {
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
border-bottom: 1pt solid #000 !important;
|
||||||
|
padding: 2pt !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signature-space {
|
||||||
|
border: 1px solid #000;
|
||||||
|
background: none;
|
||||||
|
min-height: 3rem;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
MOBILE RESPONSIVENESS
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.template-wrapper {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.values-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-content {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make principle cards full width on mobile */
|
||||||
|
.principle-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack constraint buttons vertically on mobile */
|
||||||
|
.constraint-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.constraint-buttons button {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,31 @@
|
||||||
<div class="export-section">
|
<div class="export-section">
|
||||||
<h3 class="export-title">Export Options:</h3>
|
<h3 class="export-title">Export Options:</h3>
|
||||||
<div class="export-buttons">
|
<div class="export-buttons">
|
||||||
<button
|
<button
|
||||||
@click="copyToClipboard"
|
@click="copyToClipboard"
|
||||||
class="export-btn"
|
class="export-btn"
|
||||||
:disabled="isProcessing"
|
:disabled="isProcessing"
|
||||||
ref="copyButton">
|
ref="copyButton"
|
||||||
|
>
|
||||||
<UIcon name="i-heroicons-clipboard" />
|
<UIcon name="i-heroicons-clipboard" />
|
||||||
<span>Copy as Text</span>
|
<span>Copy as Text</span>
|
||||||
<UIcon
|
<UIcon v-if="showCopySuccess" name="i-heroicons-check" class="success-icon" />
|
||||||
v-if="showCopySuccess"
|
|
||||||
name="i-heroicons-check"
|
|
||||||
class="success-icon" />
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@click="downloadAsMarkdown"
|
@click="downloadAsMarkdown"
|
||||||
class="export-btn"
|
class="export-btn"
|
||||||
:disabled="isProcessing"
|
:disabled="isProcessing"
|
||||||
ref="downloadButton">
|
ref="downloadButton"
|
||||||
|
>
|
||||||
<UIcon name="i-heroicons-arrow-down-tray" />
|
<UIcon name="i-heroicons-arrow-down-tray" />
|
||||||
<span>Download Markdown</span>
|
<span>Download Markdown</span>
|
||||||
<UIcon
|
<UIcon
|
||||||
v-if="showDownloadSuccess"
|
v-if="showDownloadSuccess"
|
||||||
name="i-heroicons-check"
|
name="i-heroicons-check"
|
||||||
class="success-icon" />
|
class="success-icon"
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -45,9 +44,9 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
filename: 'export',
|
filename: "export",
|
||||||
title: 'Export Data',
|
title: "Export Data",
|
||||||
containerClass: 'centered'
|
containerClass: "centered",
|
||||||
});
|
});
|
||||||
|
|
||||||
const isProcessing = ref(false);
|
const isProcessing = ref(false);
|
||||||
|
|
@ -58,53 +57,56 @@ const copyButton = ref<HTMLButtonElement>();
|
||||||
const downloadButton = ref<HTMLButtonElement>();
|
const downloadButton = ref<HTMLButtonElement>();
|
||||||
|
|
||||||
// Success feedback animation
|
// Success feedback animation
|
||||||
const showSuccessFeedback = (buttonRef: Ref<HTMLButtonElement | undefined>, successRef: Ref<boolean>) => {
|
const showSuccessFeedback = (
|
||||||
|
buttonRef: Ref<HTMLButtonElement | undefined>,
|
||||||
|
successRef: Ref<boolean>
|
||||||
|
) => {
|
||||||
if (!buttonRef.value) return;
|
if (!buttonRef.value) return;
|
||||||
|
|
||||||
successRef.value = true;
|
successRef.value = true;
|
||||||
|
|
||||||
// Add checkmark overlay animation
|
// Add checkmark overlay animation
|
||||||
const button = buttonRef.value;
|
const button = buttonRef.value;
|
||||||
button.classList.add('success-state');
|
button.classList.add("success-state");
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
successRef.value = false;
|
successRef.value = false;
|
||||||
button.classList.remove('success-state');
|
button.classList.remove("success-state");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyToClipboard = async () => {
|
const copyToClipboard = async () => {
|
||||||
if (isProcessing.value) return;
|
if (isProcessing.value) return;
|
||||||
|
|
||||||
isProcessing.value = true;
|
isProcessing.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const textContent = extractTextContent();
|
const textContent = extractTextContent();
|
||||||
|
|
||||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
await navigator.clipboard.writeText(textContent);
|
await navigator.clipboard.writeText(textContent);
|
||||||
} else {
|
} else {
|
||||||
// Fallback for browsers without clipboard API
|
// Fallback for browsers without clipboard API
|
||||||
const textarea = document.createElement('textarea');
|
const textarea = document.createElement("textarea");
|
||||||
textarea.value = textContent;
|
textarea.value = textContent;
|
||||||
textarea.style.position = 'fixed';
|
textarea.style.position = "fixed";
|
||||||
textarea.style.opacity = '0';
|
textarea.style.opacity = "0";
|
||||||
document.body.appendChild(textarea);
|
document.body.appendChild(textarea);
|
||||||
textarea.focus();
|
textarea.focus();
|
||||||
textarea.select();
|
textarea.select();
|
||||||
|
|
||||||
const successful = document.execCommand('copy');
|
const successful = document.execCommand("copy");
|
||||||
document.body.removeChild(textarea);
|
document.body.removeChild(textarea);
|
||||||
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
throw new Error('execCommand copy failed');
|
throw new Error("execCommand copy failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showSuccessFeedback(copyButton, showCopySuccess);
|
showSuccessFeedback(copyButton, showCopySuccess);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Copy failed:', error);
|
console.error("Copy failed:", error);
|
||||||
alert('Copy failed. Please try again or use the download option.');
|
alert("Copy failed. Please try again or use the download option.");
|
||||||
} finally {
|
} finally {
|
||||||
isProcessing.value = false;
|
isProcessing.value = false;
|
||||||
}
|
}
|
||||||
|
|
@ -112,71 +114,74 @@ const copyToClipboard = async () => {
|
||||||
|
|
||||||
const downloadAsMarkdown = () => {
|
const downloadAsMarkdown = () => {
|
||||||
if (isProcessing.value) return;
|
if (isProcessing.value) return;
|
||||||
|
|
||||||
isProcessing.value = true;
|
isProcessing.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const content = convertToMarkdown();
|
const content = convertToMarkdown();
|
||||||
downloadFile(content, `${props.filename}.md`, 'text/markdown');
|
downloadFile(content, `${props.filename}.md`, "text/markdown");
|
||||||
showSuccessFeedback(downloadButton, showDownloadSuccess);
|
showSuccessFeedback(downloadButton, showDownloadSuccess);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Markdown download failed:', error);
|
console.error("Markdown download failed:", error);
|
||||||
alert('Download failed. Please try again.');
|
alert("Download failed. Please try again.");
|
||||||
} finally {
|
} finally {
|
||||||
isProcessing.value = false;
|
isProcessing.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const extractTextContent = (): string => {
|
const extractTextContent = (): string => {
|
||||||
const today = new Date().toLocaleDateString('en-US', {
|
const today = new Date().toLocaleDateString("en-US", {
|
||||||
year: 'numeric',
|
year: "numeric",
|
||||||
month: 'long',
|
month: "long",
|
||||||
day: 'numeric'
|
day: "numeric",
|
||||||
});
|
});
|
||||||
|
|
||||||
let content = `${props.title.toUpperCase()}\n${'='.repeat(props.title.length)}\n\nExported ${today}\n\n`;
|
let content = `${props.title.toUpperCase()}\n${"=".repeat(
|
||||||
|
props.title.length
|
||||||
|
)}\n\nExported ${today}\n\n`;
|
||||||
|
|
||||||
// Convert data to readable text format
|
// Convert data to readable text format
|
||||||
if (props.exportData) {
|
if (props.exportData) {
|
||||||
content += formatDataAsText(props.exportData);
|
content += formatDataAsText(props.exportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const convertToMarkdown = (): string => {
|
const convertToMarkdown = (): string => {
|
||||||
const today = new Date().toLocaleDateString('en-US', {
|
const today = new Date().toLocaleDateString("en-US", {
|
||||||
year: 'numeric',
|
year: "numeric",
|
||||||
month: 'long',
|
month: "long",
|
||||||
day: 'numeric'
|
day: "numeric",
|
||||||
});
|
});
|
||||||
|
|
||||||
let content = `# ${props.title}\n\n*Exported ${today}*\n\n`;
|
let content = `# ${props.title}\n\n*Exported ${today}*\n\n`;
|
||||||
|
|
||||||
// Convert data to markdown format
|
// Convert data to markdown format
|
||||||
if (props.exportData) {
|
if (props.exportData) {
|
||||||
content += formatDataAsMarkdown(props.exportData);
|
content += formatDataAsMarkdown(props.exportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatDataAsText = (data: any): string => {
|
const formatDataAsText = (data: any): string => {
|
||||||
// Special handling for different template types
|
// Special handling for different template types
|
||||||
if (data.section === 'tech-charter') {
|
if (data.section === "tech-charter") {
|
||||||
return formatTechCharterAsText(data);
|
return formatTechCharterAsText(data);
|
||||||
} else if (data.section === 'membership-agreement') {
|
} else if (data.section === "membership-agreement") {
|
||||||
return formatMembershipAgreementAsText(data);
|
return formatMembershipAgreementAsText(data);
|
||||||
} else if (data.section === 'conflict-resolution-framework') {
|
} else if (data.section === "conflict-resolution-framework") {
|
||||||
return formatConflictResolutionAsText(data);
|
return formatConflictResolutionAsText(data);
|
||||||
} else if (data.section === 'decision-framework') {
|
} else if (data.section === "decision-framework") {
|
||||||
return formatDecisionFrameworkAsText(data);
|
return formatDecisionFrameworkAsText(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
return data.map((item, index) => `${index + 1}. ${formatObjectAsText(item)}`).join('\n');
|
return data
|
||||||
} else if (typeof data === 'object' && data !== null) {
|
.map((item, index) => `${index + 1}. ${formatObjectAsText(item)}`)
|
||||||
|
.join("\n");
|
||||||
|
} else if (typeof data === "object" && data !== null) {
|
||||||
return formatObjectAsText(data);
|
return formatObjectAsText(data);
|
||||||
}
|
}
|
||||||
return String(data);
|
return String(data);
|
||||||
|
|
@ -184,19 +189,21 @@ const formatDataAsText = (data: any): string => {
|
||||||
|
|
||||||
const formatDataAsMarkdown = (data: any): string => {
|
const formatDataAsMarkdown = (data: any): string => {
|
||||||
// Special handling for different template types
|
// Special handling for different template types
|
||||||
if (data.section === 'tech-charter') {
|
if (data.section === "tech-charter") {
|
||||||
return formatTechCharterAsMarkdown(data);
|
return formatTechCharterAsMarkdown(data);
|
||||||
} else if (data.section === 'membership-agreement') {
|
} else if (data.section === "membership-agreement") {
|
||||||
return formatMembershipAgreementAsMarkdown(data);
|
return formatMembershipAgreementAsMarkdown(data);
|
||||||
} else if (data.section === 'conflict-resolution-framework') {
|
} else if (data.section === "conflict-resolution-framework") {
|
||||||
return formatConflictResolutionAsMarkdown(data);
|
return formatConflictResolutionAsMarkdown(data);
|
||||||
} else if (data.section === 'decision-framework') {
|
} else if (data.section === "decision-framework") {
|
||||||
return formatDecisionFrameworkAsMarkdown(data);
|
return formatDecisionFrameworkAsMarkdown(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
return data.map((item, index) => `${index + 1}. ${formatObjectAsMarkdown(item)}`).join('\n\n');
|
return data
|
||||||
} else if (typeof data === 'object' && data !== null) {
|
.map((item, index) => `${index + 1}. ${formatObjectAsMarkdown(item)}`)
|
||||||
|
.join("\n\n");
|
||||||
|
} else if (typeof data === "object" && data !== null) {
|
||||||
return formatObjectAsMarkdown(data);
|
return formatObjectAsMarkdown(data);
|
||||||
}
|
}
|
||||||
return String(data);
|
return String(data);
|
||||||
|
|
@ -208,7 +215,7 @@ const formatTechCharterAsText = (data: any): string => {
|
||||||
const selectedPrinciples = Object.keys(data.principleWeights).filter(
|
const selectedPrinciples = Object.keys(data.principleWeights).filter(
|
||||||
(p) => data.principleWeights[p] > 0
|
(p) => data.principleWeights[p] > 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedPrinciples.filter((p) => !data.nonNegotiables.includes(p)).length > 0) {
|
if (selectedPrinciples.filter((p) => !data.nonNegotiables.includes(p)).length > 0) {
|
||||||
content += `CORE PRINCIPLES\n---------------\n\n`;
|
content += `CORE PRINCIPLES\n---------------\n\n`;
|
||||||
selectedPrinciples
|
selectedPrinciples
|
||||||
|
|
@ -245,7 +252,9 @@ const formatTechCharterAsText = (data: any): string => {
|
||||||
if (data.sortedWeights.length > 0) {
|
if (data.sortedWeights.length > 0) {
|
||||||
content += `EVALUATION RUBRIC\n-----------------\n\nScore each vendor option using these weighted criteria (0-5 scale):\n\n`;
|
content += `EVALUATION RUBRIC\n-----------------\n\nScore each vendor option using these weighted criteria (0-5 scale):\n\n`;
|
||||||
data.sortedWeights.forEach((principle: any) => {
|
data.sortedWeights.forEach((principle: any) => {
|
||||||
content += `${principle.name} (Weight: ${data.principleWeights[principle.id]})\n${principle.rubricDescription}\n\n`;
|
content += `${principle.name} (Weight: ${data.principleWeights[principle.id]})\n${
|
||||||
|
principle.rubricDescription
|
||||||
|
}\n\n`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +267,7 @@ const formatTechCharterAsMarkdown = (data: any): string => {
|
||||||
const selectedPrinciples = Object.keys(data.principleWeights).filter(
|
const selectedPrinciples = Object.keys(data.principleWeights).filter(
|
||||||
(p) => data.principleWeights[p] > 0
|
(p) => data.principleWeights[p] > 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedPrinciples.filter((p) => !data.nonNegotiables.includes(p)).length > 0) {
|
if (selectedPrinciples.filter((p) => !data.nonNegotiables.includes(p)).length > 0) {
|
||||||
content += `## Core Principles\n\n`;
|
content += `## Core Principles\n\n`;
|
||||||
selectedPrinciples
|
selectedPrinciples
|
||||||
|
|
@ -297,7 +306,9 @@ const formatTechCharterAsMarkdown = (data: any): string => {
|
||||||
content += `| Criterion | Description | Weight |\n`;
|
content += `| Criterion | Description | Weight |\n`;
|
||||||
content += `|-----------|-------------|--------|\n`;
|
content += `|-----------|-------------|--------|\n`;
|
||||||
data.sortedWeights.forEach((principle: any) => {
|
data.sortedWeights.forEach((principle: any) => {
|
||||||
content += `| ${principle.name} | ${principle.rubricDescription} | ${data.principleWeights[principle.id]} |\n`;
|
content += `| ${principle.name} | ${principle.rubricDescription} | ${
|
||||||
|
data.principleWeights[principle.id]
|
||||||
|
} |\n`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,75 +316,79 @@ const formatTechCharterAsMarkdown = (data: any): string => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatObjectAsText = (obj: any): string => {
|
const formatObjectAsText = (obj: any): string => {
|
||||||
if (!obj || typeof obj !== 'object') return String(obj);
|
if (!obj || typeof obj !== "object") return String(obj);
|
||||||
|
|
||||||
return Object.entries(obj)
|
return Object.entries(obj)
|
||||||
.filter(([key, value]) => value !== null && value !== undefined && key !== 'id')
|
.filter(([key, value]) => value !== null && value !== undefined && key !== "id")
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => {
|
||||||
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
|
const formattedKey = key
|
||||||
if (typeof value === 'object') {
|
.replace(/([A-Z])/g, " $1")
|
||||||
|
.replace(/^./, (str) => str.toUpperCase());
|
||||||
|
if (typeof value === "object") {
|
||||||
return `${formattedKey}: ${JSON.stringify(value)}`;
|
return `${formattedKey}: ${JSON.stringify(value)}`;
|
||||||
}
|
}
|
||||||
return `${formattedKey}: ${value}`;
|
return `${formattedKey}: ${value}`;
|
||||||
})
|
})
|
||||||
.join('\n');
|
.join("\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatObjectAsMarkdown = (obj: any): string => {
|
const formatObjectAsMarkdown = (obj: any): string => {
|
||||||
if (!obj || typeof obj !== 'object') return String(obj);
|
if (!obj || typeof obj !== "object") return String(obj);
|
||||||
|
|
||||||
return Object.entries(obj)
|
return Object.entries(obj)
|
||||||
.filter(([key, value]) => value !== null && value !== undefined && key !== 'id')
|
.filter(([key, value]) => value !== null && value !== undefined && key !== "id")
|
||||||
.map(([key, value]) => {
|
.map(([key, value]) => {
|
||||||
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
|
const formattedKey = key
|
||||||
if (typeof value === 'object') {
|
.replace(/([A-Z])/g, " $1")
|
||||||
|
.replace(/^./, (str) => str.toUpperCase());
|
||||||
|
if (typeof value === "object") {
|
||||||
return `**${formattedKey}**: \`${JSON.stringify(value)}\``;
|
return `**${formattedKey}**: \`${JSON.stringify(value)}\``;
|
||||||
}
|
}
|
||||||
return `**${formattedKey}**: ${value}`;
|
return `**${formattedKey}**: ${value}`;
|
||||||
})
|
})
|
||||||
.join(' \n');
|
.join(" \n");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Membership Agreement formatting
|
// Membership Agreement formatting
|
||||||
const formatMembershipAgreementAsText = (data: any): string => {
|
const formatMembershipAgreementAsText = (data: any): string => {
|
||||||
let content = `MEMBERSHIP AGREEMENT\n====================\n\n`;
|
let content = `MEMBERSHIP AGREEMENT\n====================\n\n`;
|
||||||
content += `Cooperative Name: ${data.cooperativeName}\n`;
|
content += `Cooperative Name: ${data.cooperativeName}\n`;
|
||||||
content += `Member Name: ${data.formData.memberName || '[Member Name]'}\n`;
|
content += `Member Name: ${data.formData.memberName || "[Member Name]"}\n`;
|
||||||
content += `Effective Date: ${data.formData.effectiveDate || '[Date]'}\n\n`;
|
content += `Effective Date: ${data.formData.effectiveDate || "[Date]"}\n\n`;
|
||||||
|
|
||||||
if (data.formData.purpose) {
|
if (data.formData.purpose) {
|
||||||
content += `PURPOSE\n-------\n${data.formData.purpose}\n\n`;
|
content += `PURPOSE\n-------\n${data.formData.purpose}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.formData.membershipRequirements) {
|
if (data.formData.membershipRequirements) {
|
||||||
content += `MEMBERSHIP REQUIREMENTS\n----------------------\n${data.formData.membershipRequirements}\n\n`;
|
content += `MEMBERSHIP REQUIREMENTS\n----------------------\n${data.formData.membershipRequirements}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.formData.rightsAndResponsibilities) {
|
if (data.formData.rightsAndResponsibilities) {
|
||||||
content += `RIGHTS AND RESPONSIBILITIES\n--------------------------\n${data.formData.rightsAndResponsibilities}\n\n`;
|
content += `RIGHTS AND RESPONSIBILITIES\n--------------------------\n${data.formData.rightsAndResponsibilities}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatMembershipAgreementAsMarkdown = (data: any): string => {
|
const formatMembershipAgreementAsMarkdown = (data: any): string => {
|
||||||
let content = `## Membership Agreement\n\n`;
|
let content = `## Membership Agreement\n\n`;
|
||||||
content += `**Cooperative Name:** ${data.cooperativeName} \n`;
|
content += `**Cooperative Name:** ${data.cooperativeName} \n`;
|
||||||
content += `**Member Name:** ${data.formData.memberName || '[Member Name]'} \n`;
|
content += `**Member Name:** ${data.formData.memberName || "[Member Name]"} \n`;
|
||||||
content += `**Effective Date:** ${data.formData.effectiveDate || '[Date]'} \n\n`;
|
content += `**Effective Date:** ${data.formData.effectiveDate || "[Date]"} \n\n`;
|
||||||
|
|
||||||
if (data.formData.purpose) {
|
if (data.formData.purpose) {
|
||||||
content += `### Purpose\n\n${data.formData.purpose}\n\n`;
|
content += `### Purpose\n\n${data.formData.purpose}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.formData.membershipRequirements) {
|
if (data.formData.membershipRequirements) {
|
||||||
content += `### Membership Requirements\n\n${data.formData.membershipRequirements}\n\n`;
|
content += `### Membership Requirements\n\n${data.formData.membershipRequirements}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.formData.rightsAndResponsibilities) {
|
if (data.formData.rightsAndResponsibilities) {
|
||||||
content += `### Rights and Responsibilities\n\n${data.formData.rightsAndResponsibilities}\n\n`;
|
content += `### Rights and Responsibilities\n\n${data.formData.rightsAndResponsibilities}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -383,33 +398,35 @@ const formatConflictResolutionAsText = (data: any): string => {
|
||||||
content += `Organization: ${data.orgName}\n`;
|
content += `Organization: ${data.orgName}\n`;
|
||||||
content += `Organization Type: ${data.orgType}\n`;
|
content += `Organization Type: ${data.orgType}\n`;
|
||||||
content += `Member Count: ${data.memberCount}\n\n`;
|
content += `Member Count: ${data.memberCount}\n\n`;
|
||||||
|
|
||||||
if (data.coreValues?.length > 0) {
|
if (data.coreValues?.length > 0) {
|
||||||
content += `CORE VALUES\n-----------\n`;
|
content += `CORE VALUES\n-----------\n`;
|
||||||
data.coreValues.forEach((value: string, index: number) => {
|
data.coreValues.forEach((value: string, index: number) => {
|
||||||
content += `${index + 1}. ${value}\n`;
|
content += `${index + 1}. ${value}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.principles?.length > 0) {
|
if (data.principles?.length > 0) {
|
||||||
content += `PRINCIPLES\n----------\n`;
|
content += `PRINCIPLES\n----------\n`;
|
||||||
data.principles.forEach((principle: string, index: number) => {
|
data.principles.forEach((principle: string, index: number) => {
|
||||||
content += `${index + 1}. ${principle}\n`;
|
content += `${index + 1}. ${principle}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.policies) {
|
if (data.policies) {
|
||||||
content += `POLICIES\n--------\n`;
|
content += `POLICIES\n--------\n`;
|
||||||
Object.entries(data.policies).forEach(([key, value]) => {
|
Object.entries(data.policies).forEach(([key, value]) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
|
const formattedKey = key
|
||||||
|
.replace(/([A-Z])/g, " $1")
|
||||||
|
.replace(/^./, (str) => str.toUpperCase());
|
||||||
content += `${formattedKey}: ${value}\n`;
|
content += `${formattedKey}: ${value}\n`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -418,40 +435,42 @@ const formatConflictResolutionAsMarkdown = (data: any): string => {
|
||||||
content += `**Organization:** ${data.orgName} \n`;
|
content += `**Organization:** ${data.orgName} \n`;
|
||||||
content += `**Organization Type:** ${data.orgType} \n`;
|
content += `**Organization Type:** ${data.orgType} \n`;
|
||||||
content += `**Member Count:** ${data.memberCount} \n\n`;
|
content += `**Member Count:** ${data.memberCount} \n\n`;
|
||||||
|
|
||||||
if (data.coreValues?.length > 0) {
|
if (data.coreValues?.length > 0) {
|
||||||
content += `### Core Values\n\n`;
|
content += `### Core Values\n\n`;
|
||||||
data.coreValues.forEach((value: string, index: number) => {
|
data.coreValues.forEach((value: string, index: number) => {
|
||||||
content += `${index + 1}. ${value}\n`;
|
content += `${index + 1}. ${value}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.principles?.length > 0) {
|
if (data.principles?.length > 0) {
|
||||||
content += `### Principles\n\n`;
|
content += `### Principles\n\n`;
|
||||||
data.principles.forEach((principle: string, index: number) => {
|
data.principles.forEach((principle: string, index: number) => {
|
||||||
content += `${index + 1}. ${principle}\n`;
|
content += `${index + 1}. ${principle}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.policies) {
|
if (data.policies) {
|
||||||
content += `### Policies\n\n`;
|
content += `### Policies\n\n`;
|
||||||
Object.entries(data.policies).forEach(([key, value]) => {
|
Object.entries(data.policies).forEach(([key, value]) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
|
const formattedKey = key
|
||||||
|
.replace(/([A-Z])/g, " $1")
|
||||||
|
.replace(/^./, (str) => str.toUpperCase());
|
||||||
content += `**${formattedKey}:** ${value} \n`;
|
content += `**${formattedKey}:** ${value} \n`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Decision Framework formatting
|
// Decision Framework formatting
|
||||||
const formatDecisionFrameworkAsText = (data: any): string => {
|
const formatDecisionFrameworkAsText = (data: any): string => {
|
||||||
let content = `DECISION FRAMEWORK RESULTS\n=========================\n\n`;
|
let content = `DECISION FRAMEWORK RESULTS\n=========================\n\n`;
|
||||||
|
|
||||||
if (data.surveyResponses) {
|
if (data.surveyResponses) {
|
||||||
content += `SURVEY RESPONSES\n----------------\n`;
|
content += `SURVEY RESPONSES\n----------------\n`;
|
||||||
content += `Urgency: ${data.surveyResponses.urgency}\n`;
|
content += `Urgency: ${data.surveyResponses.urgency}\n`;
|
||||||
|
|
@ -462,37 +481,37 @@ const formatDecisionFrameworkAsText = (data: any): string => {
|
||||||
content += `Investment: ${data.surveyResponses.investment}\n`;
|
content += `Investment: ${data.surveyResponses.investment}\n`;
|
||||||
content += `Team Size: ${data.surveyResponses.teamSize}\n\n`;
|
content += `Team Size: ${data.surveyResponses.teamSize}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.recommendedFramework) {
|
if (data.recommendedFramework) {
|
||||||
const framework = data.recommendedFramework;
|
const framework = data.recommendedFramework;
|
||||||
content += `RECOMMENDED FRAMEWORK\n--------------------\n`;
|
content += `RECOMMENDED FRAMEWORK\n--------------------\n`;
|
||||||
content += `Method: ${framework.method}\n`;
|
content += `Method: ${framework.method}\n`;
|
||||||
content += `Tagline: ${framework.tagline}\n\n`;
|
content += `Tagline: ${framework.tagline}\n\n`;
|
||||||
content += `Reasoning: ${framework.reasoning}\n\n`;
|
content += `Reasoning: ${framework.reasoning}\n\n`;
|
||||||
|
|
||||||
if (framework.steps) {
|
if (framework.steps) {
|
||||||
content += `IMPLEMENTATION STEPS\n-------------------\n`;
|
content += `IMPLEMENTATION STEPS\n-------------------\n`;
|
||||||
framework.steps.forEach((step: string, index: number) => {
|
framework.steps.forEach((step: string, index: number) => {
|
||||||
content += `${index + 1}. ${step}\n`;
|
content += `${index + 1}. ${step}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (framework.tips) {
|
if (framework.tips) {
|
||||||
content += `PRO TIPS\n--------\n`;
|
content += `PRO TIPS\n--------\n`;
|
||||||
framework.tips.forEach((tip: string, index: number) => {
|
framework.tips.forEach((tip: string, index: number) => {
|
||||||
content += `${index + 1}. ${tip}\n`;
|
content += `${index + 1}. ${tip}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatDecisionFrameworkAsMarkdown = (data: any): string => {
|
const formatDecisionFrameworkAsMarkdown = (data: any): string => {
|
||||||
let content = `## Decision Framework Results\n\n`;
|
let content = `## Decision Framework Results\n\n`;
|
||||||
|
|
||||||
if (data.surveyResponses) {
|
if (data.surveyResponses) {
|
||||||
content += `### Survey Responses\n\n`;
|
content += `### Survey Responses\n\n`;
|
||||||
content += `**Urgency:** ${data.surveyResponses.urgency} \n`;
|
content += `**Urgency:** ${data.surveyResponses.urgency} \n`;
|
||||||
|
|
@ -503,38 +522,38 @@ const formatDecisionFrameworkAsMarkdown = (data: any): string => {
|
||||||
content += `**Investment:** ${data.surveyResponses.investment} \n`;
|
content += `**Investment:** ${data.surveyResponses.investment} \n`;
|
||||||
content += `**Team Size:** ${data.surveyResponses.teamSize} \n\n`;
|
content += `**Team Size:** ${data.surveyResponses.teamSize} \n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.recommendedFramework) {
|
if (data.recommendedFramework) {
|
||||||
const framework = data.recommendedFramework;
|
const framework = data.recommendedFramework;
|
||||||
content += `### Recommended Framework\n\n`;
|
content += `### Recommended Framework\n\n`;
|
||||||
content += `**Method:** ${framework.method} \n`;
|
content += `**Method:** ${framework.method} \n`;
|
||||||
content += `**Tagline:** ${framework.tagline} \n\n`;
|
content += `**Tagline:** ${framework.tagline} \n\n`;
|
||||||
content += `**Reasoning:** ${framework.reasoning}\n\n`;
|
content += `**Reasoning:** ${framework.reasoning}\n\n`;
|
||||||
|
|
||||||
if (framework.steps) {
|
if (framework.steps) {
|
||||||
content += `#### Implementation Steps\n\n`;
|
content += `#### Implementation Steps\n\n`;
|
||||||
framework.steps.forEach((step: string, index: number) => {
|
framework.steps.forEach((step: string, index: number) => {
|
||||||
content += `${index + 1}. ${step}\n`;
|
content += `${index + 1}. ${step}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (framework.tips) {
|
if (framework.tips) {
|
||||||
content += `#### Pro Tips\n\n`;
|
content += `#### Pro Tips\n\n`;
|
||||||
framework.tips.forEach((tip: string, index: number) => {
|
framework.tips.forEach((tip: string, index: number) => {
|
||||||
content += `${index + 1}. ${tip}\n`;
|
content += `${index + 1}. ${tip}\n`;
|
||||||
});
|
});
|
||||||
content += '\n';
|
content += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadFile = (content: string, filename: string, type: string) => {
|
const downloadFile = (content: string, filename: string, type: string) => {
|
||||||
const blob = new Blob([content], { type });
|
const blob = new Blob([content], { type });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = filename;
|
a.download = filename;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
|
|
@ -545,31 +564,7 @@ const downloadFile = (content: string, filename: string, type: string) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.export-options {
|
@reference "tailwindcss";
|
||||||
margin: 2rem auto;
|
|
||||||
background: white;
|
|
||||||
border: 2px solid #000;
|
|
||||||
position: relative;
|
|
||||||
box-shadow: 4px 4px 0px #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-options.centered {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-options::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 2px;
|
|
||||||
left: 2px;
|
|
||||||
right: -2px;
|
|
||||||
bottom: -2px;
|
|
||||||
background: #000;
|
|
||||||
background-image: radial-gradient(white 1px, transparent 1px);
|
|
||||||
background-size: 3px 3px;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-content {
|
.export-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
@ -592,31 +587,8 @@ const downloadFile = (content: string, filename: string, type: string) => {
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-title {
|
|
||||||
font-weight: 700;
|
|
||||||
color: #374151;
|
|
||||||
margin: 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn {
|
.export-btn {
|
||||||
background: #f9fafb;
|
@apply bg-neutral-100 dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 text-neutral-900 dark:text-white;
|
||||||
border: 2px solid #000;
|
|
||||||
color: #374151;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: 600;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
text-decoration: none;
|
|
||||||
min-width: fit-content;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-btn:hover:not(:disabled) {
|
.export-btn:hover:not(:disabled) {
|
||||||
|
|
@ -667,52 +639,25 @@ const downloadFile = (content: string, filename: string, type: string) => {
|
||||||
transform: translateY(-50%) scale(1);
|
transform: translateY(-50%) scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark mode styles */
|
|
||||||
html.dark .export-options {
|
|
||||||
background: #0a0a0a;
|
|
||||||
border-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark .export-options::before {
|
|
||||||
background: white;
|
|
||||||
background-image: radial-gradient(black 1px, transparent 1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark .export-title {
|
|
||||||
color: #e5e7eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark .export-btn {
|
|
||||||
background: #0a0a0a;
|
|
||||||
border-color: white;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark .export-btn:hover:not(:disabled) {
|
|
||||||
background: white;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile responsive */
|
/* Mobile responsive */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.export-content {
|
.export-content {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-section {
|
.export-section {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-buttons {
|
.export-buttons {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-btn {
|
.export-btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 140px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,12 @@
|
||||||
<WizardSubnav />
|
<WizardSubnav />
|
||||||
|
|
||||||
<!-- Export Options - Top -->
|
<!-- Export Options - Top -->
|
||||||
<div class="flex justify-center py-6">
|
|
||||||
<ExportOptions
|
<ExportOptions
|
||||||
:export-data="exportData"
|
:export-data="exportData"
|
||||||
filename="conflict-resolution-framework"
|
filename="conflict-resolution-framework"
|
||||||
title="Conflict Resolution Framework"
|
title="Conflict Resolution Framework"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"
|
class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"
|
||||||
|
|
@ -822,13 +821,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Export Options - Bottom -->
|
<!-- Export Options - Bottom -->
|
||||||
<div class="flex justify-center py-6">
|
|
||||||
<ExportOptions
|
<ExportOptions
|
||||||
:export-data="exportData"
|
:export-data="exportData"
|
||||||
filename="conflict-resolution-framework"
|
filename="conflict-resolution-framework"
|
||||||
title="Conflict Resolution Framework"
|
title="Conflict Resolution Framework"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -1392,57 +1389,9 @@ const exportData = computed(() => ({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* Ubuntu font import */
|
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500;700&family=Ubuntu+Mono:wght@400;700&display=swap");
|
|
||||||
@reference "tailwindcss";
|
@reference "tailwindcss";
|
||||||
|
|
||||||
/* Template wrapper and document styling */
|
/* Template-specific styles that aren't in main.css */
|
||||||
/* rely on Tailwind bg utilities applied on wrapper */
|
|
||||||
.template-wrapper {
|
|
||||||
min-height: 100vh;
|
|
||||||
padding: 2rem;
|
|
||||||
font-family: "Ubuntu", monospace;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.template-wrapper::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-image: radial-gradient(circle at 25% 25%, black 1px, transparent 1px),
|
|
||||||
radial-gradient(circle at 75% 75%, black 1px, transparent 1px);
|
|
||||||
background-size: 8px 8px, 8px 8px;
|
|
||||||
background-position: 0 0, 4px 4px;
|
|
||||||
opacity: 0.1;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.document-page::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 4px;
|
|
||||||
left: 4px;
|
|
||||||
right: -4px;
|
|
||||||
bottom: -4px;
|
|
||||||
background: black;
|
|
||||||
background-image: radial-gradient(white 1px, transparent 1px);
|
|
||||||
background-size: 2px 2px;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
.document-page::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
border: 1px solid black;
|
|
||||||
z-index: 1;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Progress bar */
|
/* Progress bar */
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
|
|
@ -1461,30 +1410,6 @@ const exportData = computed(() => ({
|
||||||
transition: width 0.3s ease;
|
transition: width 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Document header */
|
|
||||||
.document-header {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.document-title {
|
|
||||||
font-size: 2.25rem;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
|
|
||||||
margin: 0 0 0.5rem;
|
|
||||||
padding: 1rem 0;
|
|
||||||
border-top: 2px solid #111827;
|
|
||||||
border-bottom: 2px solid #111827;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
color: #666;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quick start section */
|
/* Quick start section */
|
||||||
.quick-start {
|
.quick-start {
|
||||||
background: #f0f7ff;
|
background: #f0f7ff;
|
||||||
|
|
@ -1528,11 +1453,6 @@ const exportData = computed(() => ({
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Section styling */
|
|
||||||
.section-card {
|
|
||||||
@apply border border-neutral-200 dark:border-neutral-800 rounded-lg p-5 mb-8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Styling for sections when toggled off */
|
/* Styling for sections when toggled off */
|
||||||
.section-card:has(.space-y-6[style*="display: none"]) {
|
.section-card:has(.space-y-6[style*="display: none"]) {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
@ -1542,17 +1462,6 @@ const exportData = computed(() => ({
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-header {
|
|
||||||
/* presentational container only */
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
font-weight: 800;
|
|
||||||
color: inherit;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Toggle styling */
|
/* Toggle styling */
|
||||||
.toggle-section {
|
.toggle-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -1589,84 +1498,6 @@ const exportData = computed(() => ({
|
||||||
transform: translateX(24px);
|
transform: translateX(24px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Form styling */
|
|
||||||
.form-group-large {
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure form field containers are also full-width */
|
|
||||||
.form-group-large {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group-large > * {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure consistent alignment for all form fields */
|
|
||||||
.form-group-large :deep(textarea),
|
|
||||||
.form-group-large :deep(input),
|
|
||||||
.form-group-large :deep(select),
|
|
||||||
.form-group-large :deep(.ui-select),
|
|
||||||
.form-group-large :deep(.ui-input),
|
|
||||||
.form-group-large :deep(.ui-textarea) {
|
|
||||||
margin-left: 0 !important;
|
|
||||||
padding-left: 0.75rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Additional targeting for UInput, USelect, UTextarea components */
|
|
||||||
.form-group-large :deep(.u-input),
|
|
||||||
.form-group-large :deep(.u-select),
|
|
||||||
.form-group-large :deep(.u-textarea),
|
|
||||||
.form-group-large :deep([data-headlessui-state]),
|
|
||||||
.form-group-large :deep(.relative) {
|
|
||||||
margin-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group-large :deep(.u-input input),
|
|
||||||
.form-group-large :deep(.u-select select),
|
|
||||||
.form-group-large :deep(.u-textarea textarea) {
|
|
||||||
margin-left: 0 !important;
|
|
||||||
padding-left: 0.75rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-text {
|
|
||||||
/* moved to inline classes */
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-group {
|
|
||||||
@apply flex flex-col space-y-3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-item {
|
|
||||||
@apply flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Approach radio styling removed - using pure Tailwind classes */
|
|
||||||
|
|
||||||
.values-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
||||||
gap: 0.75rem;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inline-field {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 0.25rem;
|
|
||||||
min-width: 120px;
|
|
||||||
border: none;
|
|
||||||
background: #f9fafb;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-paragraph {
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validation error styling */
|
/* Validation error styling */
|
||||||
.validation-error {
|
.validation-error {
|
||||||
color: #ef4444;
|
color: #ef4444;
|
||||||
|
|
@ -1702,21 +1533,6 @@ const exportData = computed(() => ({
|
||||||
background: #5856eb;
|
background: #5856eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bottom export controls */
|
|
||||||
|
|
||||||
.export-buttons-bottom {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 1rem;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn.large svg {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-preview-btn {
|
.close-preview-btn {
|
||||||
background: #ef4444;
|
background: #ef4444;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
@ -1857,169 +1673,4 @@ html.dark .policy-preview code {
|
||||||
.policy-preview em {
|
.policy-preview em {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Export controls */
|
|
||||||
|
|
||||||
.export-btn {
|
|
||||||
/* retained for bitmap overrides below; core layout now via Tailwind */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide elements from print */
|
|
||||||
.no-print,
|
|
||||||
.no-pdf {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print styles */
|
|
||||||
@media print {
|
|
||||||
.no-print,
|
|
||||||
.no-pdf {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-wrapper {
|
|
||||||
background: white !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.document-page {
|
|
||||||
max-width: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.document-title {
|
|
||||||
font-size: 18pt;
|
|
||||||
background: none;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 14pt;
|
|
||||||
page-break-after: avoid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-card {
|
|
||||||
break-inside: avoid;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
padding: 0.5rem;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-item {
|
|
||||||
font-size: 10pt;
|
|
||||||
margin: 2pt 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inline-field {
|
|
||||||
background: none !important;
|
|
||||||
border: none !important;
|
|
||||||
border-bottom: 1pt solid #000 !important;
|
|
||||||
padding: 2pt !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bitmap aesthetic overrides - remove all rounded corners */
|
|
||||||
* {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
font-family: "Ubuntu", monospace !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Form fields with bitmap styling */
|
|
||||||
input,
|
|
||||||
textarea,
|
|
||||||
select {
|
|
||||||
border: 1px solid black !important;
|
|
||||||
background: white !important;
|
|
||||||
color: black !important;
|
|
||||||
font-family: "Ubuntu Mono", monospace !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus,
|
|
||||||
textarea:focus,
|
|
||||||
select:focus {
|
|
||||||
outline: 2px solid black !important;
|
|
||||||
outline-offset: -2px !important;
|
|
||||||
background: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark mode form fields */
|
|
||||||
html.dark input,
|
|
||||||
html.dark textarea,
|
|
||||||
html.dark select {
|
|
||||||
border: 1px solid white !important;
|
|
||||||
background: #0a0a0a !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.dark input:focus,
|
|
||||||
html.dark textarea:focus,
|
|
||||||
html.dark select:focus {
|
|
||||||
outline: 2px solid white !important;
|
|
||||||
background: #0a0a0a !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn {
|
|
||||||
@apply bg-white border border-black text-black font-mono uppercase font-normal tracking-wide;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn:hover {
|
|
||||||
@apply bg-black text-white -translate-x-px -translate-y-px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn.primary {
|
|
||||||
@apply bg-black text-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-btn.primary:hover {
|
|
||||||
@apply bg-black -translate-x-px -translate-y-px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove any card styling roundness */
|
|
||||||
.section-card,
|
|
||||||
.form-group-large {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Document titles */
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
font-family: "Ubuntu", monospace !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All text */
|
|
||||||
p,
|
|
||||||
span,
|
|
||||||
div {
|
|
||||||
color: inherit !important;
|
|
||||||
font-family: "Ubuntu", monospace !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile responsiveness */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.template-wrapper {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preset-buttons {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.values-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.export-content {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -4,34 +4,39 @@
|
||||||
<WizardSubnav />
|
<WizardSubnav />
|
||||||
|
|
||||||
<!-- Export Options at Top -->
|
<!-- Export Options at Top -->
|
||||||
<div class="flex justify-center py-6">
|
<ExportOptions
|
||||||
<ExportOptions
|
:export-data="exportData"
|
||||||
:export-data="exportData"
|
filename="decision-framework"
|
||||||
filename="decision-framework"
|
title="Decision Framework Helper"
|
||||||
title="Decision Framework Helper" />
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"
|
class="template-wrapper bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100"
|
||||||
style="font-family: 'Ubuntu', monospace">
|
style="font-family: 'Ubuntu', monospace"
|
||||||
|
>
|
||||||
<!-- Spacer for consistency -->
|
<!-- Spacer for consistency -->
|
||||||
<div class="py-4"></div>
|
<div class="py-4"></div>
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto relative px-4">
|
<div class="max-w-4xl mx-auto relative px-4">
|
||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-neutral-950 border-2 border-neutral-900 dark:border-neutral-100 decision-framework-container">
|
class="bg-white dark:bg-neutral-950 border-2 border-neutral-900 dark:border-neutral-100 decision-framework-container"
|
||||||
|
>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div
|
<div
|
||||||
class="bg-black dark:bg-white text-white dark:text-black px-8 py-12 text-center header-section">
|
class="bg-black dark:bg-white text-white dark:text-black px-8 py-12 text-center header-section"
|
||||||
|
>
|
||||||
<!-- Dithered shadow background -->
|
<!-- Dithered shadow background -->
|
||||||
<div
|
<div
|
||||||
class="absolute top-4 left-4 right-0 bottom-0 dither-shadow-header"></div>
|
class="absolute top-4 left-4 right-0 bottom-0 dither-shadow-header"
|
||||||
|
></div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="relative bg-black dark:bg-white text-white dark:text-black px-4 py-4 border-2 border-neutral-100 dark:border-neutral-900">
|
class="relative bg-black dark:bg-white text-white dark:text-black px-4 py-4 border-2 border-neutral-100 dark:border-neutral-900"
|
||||||
|
>
|
||||||
<h1
|
<h1
|
||||||
class="text-3xl font-bold mb-2 uppercase"
|
class="text-3xl font-bold mb-2 uppercase"
|
||||||
style="font-family: 'Ubuntu', monospace">
|
style="font-family: 'Ubuntu', monospace"
|
||||||
|
>
|
||||||
Decision Framework Helper
|
Decision Framework Helper
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-lg" style="font-family: 'Ubuntu', monospace">
|
<p class="text-lg" style="font-family: 'Ubuntu', monospace">
|
||||||
|
|
@ -41,24 +46,22 @@
|
||||||
<!-- Progress Bar -->
|
<!-- Progress Bar -->
|
||||||
<div v-if="!showResult" class="mt-8">
|
<div v-if="!showResult" class="mt-8">
|
||||||
<div class="flex justify-between items-center mb-2">
|
<div class="flex justify-between items-center mb-2">
|
||||||
<span
|
<span class="text-sm" style="font-family: 'Ubuntu Mono', monospace"
|
||||||
class="text-sm"
|
|
||||||
style="font-family: 'Ubuntu Mono', monospace"
|
|
||||||
>Step {{ currentStep }} of {{ totalSteps }}</span
|
>Step {{ currentStep }} of {{ totalSteps }}</span
|
||||||
>
|
>
|
||||||
<span
|
<span class="text-sm" style="font-family: 'Ubuntu Mono', monospace"
|
||||||
class="text-sm"
|
|
||||||
style="font-family: 'Ubuntu Mono', monospace"
|
|
||||||
>{{ Math.round((currentStep / totalSteps) * 100) }}%</span
|
>{{ Math.round((currentStep / totalSteps) * 100) }}%</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="w-full bg-white dark:bg-black h-2 border-2 border-neutral-100 dark:border-neutral-900">
|
class="w-full bg-white dark:bg-black h-2 border-2 border-neutral-100 dark:border-neutral-900"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="bg-black dark:bg-white h-full transition-all duration-300 progress-dither"
|
class="bg-black dark:bg-white h-full transition-all duration-300 progress-dither"
|
||||||
:style="{
|
:style="{
|
||||||
width: (currentStep / totalSteps) * 100 + '%',
|
width: (currentStep / totalSteps) * 100 + '%',
|
||||||
}"></div>
|
}"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -72,14 +75,15 @@
|
||||||
<div v-if="currentStep === 1">
|
<div v-if="currentStep === 1">
|
||||||
<div
|
<div
|
||||||
class="font-semibold text-black dark:text-white mb-6 text-2xl"
|
class="font-semibold text-black dark:text-white mb-6 text-2xl"
|
||||||
style="font-family: 'Ubuntu', monospace">
|
style="font-family: 'Ubuntu', monospace"
|
||||||
|
>
|
||||||
How urgent is this decision?
|
How urgent is this decision?
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bg-white dark:bg-neutral-950 p-8 border-2 border-neutral-900 dark:border-neutral-100 relative">
|
class="bg-white dark:bg-neutral-950 p-8 border-2 border-neutral-900 dark:border-neutral-100 relative"
|
||||||
|
>
|
||||||
<!-- Dithered shadow background -->
|
<!-- Dithered shadow background -->
|
||||||
<div
|
<div class="absolute top-2 left-2 right-0 bottom-0 dither-shadow"></div>
|
||||||
class="absolute top-2 left-2 right-0 bottom-0 dither-shadow"></div>
|
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="flex justify-between mb-6 text-sm">
|
<div class="flex justify-between mb-6 text-sm">
|
||||||
|
|
@ -101,10 +105,12 @@
|
||||||
min="1"
|
min="1"
|
||||||
max="5"
|
max="5"
|
||||||
step="1"
|
step="1"
|
||||||
class="w-full h-2 bg-white dark:bg-black appearance-none cursor-pointer slider" />
|
class="w-full h-2 bg-white dark:bg-black appearance-none cursor-pointer slider"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
class="flex justify-between mt-4 text-sm text-black dark:text-white"
|
class="flex justify-between mt-4 text-sm text-black dark:text-white"
|
||||||
style="font-family: 'Ubuntu Mono', monospace">
|
style="font-family: 'Ubuntu Mono', monospace"
|
||||||
|
>
|
||||||
<span>1</span>
|
<span>1</span>
|
||||||
<span>2</span>
|
<span>2</span>
|
||||||
<span>3</span>
|
<span>3</span>
|
||||||
|
|
@ -120,7 +126,8 @@
|
||||||
<div v-if="currentStep === 2">
|
<div v-if="currentStep === 2">
|
||||||
<div
|
<div
|
||||||
class="font-semibold text-black mb-6 text-2xl"
|
class="font-semibold text-black mb-6 text-2xl"
|
||||||
style="font-family: 'Ubuntu', monospace">
|
style="font-family: 'Ubuntu', monospace"
|
||||||
|
>
|
||||||
Can we change our minds later?
|
Can we change our minds later?
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-4">
|
<div class="grid gap-4">
|
||||||
|
|
@ -133,7 +140,8 @@
|
||||||
? 'border-violet-700 bg-violet-700 text-white'
|
? 'border-violet-700 bg-violet-700 text-white'
|
||||||
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('reversible', option.value)">
|
@click="selectOption('reversible', option.value)"
|
||||||
|
>
|
||||||
<div class="font-semibold mb-1">{{ option.title }}</div>
|
<div class="font-semibold mb-1">{{ option.title }}</div>
|
||||||
<div class="text-sm opacity-85">
|
<div class="text-sm opacity-85">
|
||||||
{{ option.description }}
|
{{ option.description }}
|
||||||
|
|
@ -157,7 +165,8 @@
|
||||||
? 'border-violet-700 bg-violet-700 text-white'
|
? 'border-violet-700 bg-violet-700 text-white'
|
||||||
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('expertise', option.value)">
|
@click="selectOption('expertise', option.value)"
|
||||||
|
>
|
||||||
<div class="font-semibold mb-1">{{ option.title }}</div>
|
<div class="font-semibold mb-1">{{ option.title }}</div>
|
||||||
<div class="text-sm opacity-85">
|
<div class="text-sm opacity-85">
|
||||||
{{ option.description }}
|
{{ option.description }}
|
||||||
|
|
@ -181,7 +190,8 @@
|
||||||
? 'border-violet-700 bg-violet-700 text-white'
|
? 'border-violet-700 bg-violet-700 text-white'
|
||||||
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('impact', option.value)">
|
@click="selectOption('impact', option.value)"
|
||||||
|
>
|
||||||
<div class="font-semibold mb-1">{{ option.title }}</div>
|
<div class="font-semibold mb-1">{{ option.title }}</div>
|
||||||
<div class="text-sm opacity-85">
|
<div class="text-sm opacity-85">
|
||||||
{{ option.description }}
|
{{ option.description }}
|
||||||
|
|
@ -205,7 +215,8 @@
|
||||||
? 'border-violet-700 bg-violet-700 text-white'
|
? 'border-violet-700 bg-violet-700 text-white'
|
||||||
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('options', option.value)">
|
@click="selectOption('options', option.value)"
|
||||||
|
>
|
||||||
<div class="font-semibold mb-1">{{ option.title }}</div>
|
<div class="font-semibold mb-1">{{ option.title }}</div>
|
||||||
<div class="text-sm opacity-85">
|
<div class="text-sm opacity-85">
|
||||||
{{ option.description }}
|
{{ option.description }}
|
||||||
|
|
@ -229,7 +240,8 @@
|
||||||
? 'border-violet-700 bg-violet-700 text-white'
|
? 'border-violet-700 bg-violet-700 text-white'
|
||||||
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('investment', option.value)">
|
@click="selectOption('investment', option.value)"
|
||||||
|
>
|
||||||
<div class="font-semibold mb-1">{{ option.title }}</div>
|
<div class="font-semibold mb-1">{{ option.title }}</div>
|
||||||
<div class="text-sm opacity-85">
|
<div class="text-sm opacity-85">
|
||||||
{{ option.description }}
|
{{ option.description }}
|
||||||
|
|
@ -253,7 +265,8 @@
|
||||||
? 'bg-violet-700 text-white border-violet-700'
|
? 'bg-violet-700 text-white border-violet-700'
|
||||||
: 'bg-white text-neutral-700 border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
: 'bg-white text-neutral-700 border-neutral-200 hover:border-violet-700 hover:bg-violet-50',
|
||||||
]"
|
]"
|
||||||
@click="selectOption('teamSize', size)">
|
@click="selectOption('teamSize', size)"
|
||||||
|
>
|
||||||
{{ size }}
|
{{ size }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -261,11 +274,13 @@
|
||||||
|
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<div
|
<div
|
||||||
class="flex justify-between items-center mt-12 pt-8 border-t-2 border-neutral-200">
|
class="flex justify-between items-center mt-12 pt-8 border-t-2 border-neutral-200"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-if="currentStep > 1"
|
v-if="currentStep > 1"
|
||||||
@click="previousStep"
|
@click="previousStep"
|
||||||
class="px-6 py-3 text-violet-700 border-2 border-violet-700 rounded-md hover:bg-violet-50 transition-all duration-200">
|
class="px-6 py-3 text-violet-700 border-2 border-violet-700 rounded-md hover:bg-violet-50 transition-all duration-200"
|
||||||
|
>
|
||||||
← Previous
|
← Previous
|
||||||
</button>
|
</button>
|
||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
|
|
@ -273,13 +288,15 @@
|
||||||
<button
|
<button
|
||||||
v-if="canProceed && currentStep < totalSteps"
|
v-if="canProceed && currentStep < totalSteps"
|
||||||
@click="nextStep"
|
@click="nextStep"
|
||||||
class="px-6 py-3 bg-violet-700 text-white rounded-md hover:bg-violet-800 transition-all duration-200">
|
class="px-6 py-3 bg-violet-700 text-white rounded-md hover:bg-violet-800 transition-all duration-200"
|
||||||
|
>
|
||||||
Next →
|
Next →
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-else-if="canProceed && currentStep === totalSteps"
|
v-else-if="canProceed && currentStep === totalSteps"
|
||||||
@click="showRecommendation"
|
@click="showRecommendation"
|
||||||
class="px-6 py-3 bg-violet-700 text-white rounded-md hover:bg-violet-800 transition-all duration-200">
|
class="px-6 py-3 bg-violet-700 text-white rounded-md hover:bg-violet-800 transition-all duration-200"
|
||||||
|
>
|
||||||
Get Recommendation
|
Get Recommendation
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -289,7 +306,8 @@
|
||||||
<div
|
<div
|
||||||
v-if="showResult"
|
v-if="showResult"
|
||||||
data-results
|
data-results
|
||||||
class="border-t-2 border-neutral-200 pt-12">
|
class="border-t-2 border-neutral-200 pt-12"
|
||||||
|
>
|
||||||
<UCard class="bg-neutral-50">
|
<UCard class="bg-neutral-50">
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<h2 class="text-2xl font-semibold text-violet-700 mb-2">
|
<h2 class="text-2xl font-semibold text-violet-700 mb-2">
|
||||||
|
|
@ -317,10 +335,9 @@
|
||||||
<li
|
<li
|
||||||
v-for="step in result.steps"
|
v-for="step in result.steps"
|
||||||
:key="step"
|
:key="step"
|
||||||
class="flex items-start">
|
class="flex items-start"
|
||||||
<span class="text-violet-700 font-bold mr-3 mt-1"
|
>
|
||||||
>→</span
|
<span class="text-violet-700 font-bold mr-3 mt-1">→</span>
|
||||||
>
|
|
||||||
<span class="text-neutral-700">{{ step }}</span>
|
<span class="text-neutral-700">{{ step }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -334,10 +351,9 @@
|
||||||
<li
|
<li
|
||||||
v-for="tip in result.tips"
|
v-for="tip in result.tips"
|
||||||
:key="tip"
|
:key="tip"
|
||||||
class="flex items-start">
|
class="flex items-start"
|
||||||
<span class="text-violet-700 font-bold mr-3 mt-1"
|
>
|
||||||
>→</span
|
<span class="text-violet-700 font-bold mr-3 mt-1">→</span>
|
||||||
>
|
|
||||||
<span class="text-neutral-700">{{ tip }}</span>
|
<span class="text-neutral-700">{{ tip }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -351,7 +367,8 @@
|
||||||
variant="soft"
|
variant="soft"
|
||||||
:title="'Watch out for:'"
|
:title="'Watch out for:'"
|
||||||
:description="result.warning"
|
:description="result.warning"
|
||||||
class="mb-6" />
|
class="mb-6"
|
||||||
|
/>
|
||||||
|
|
||||||
<UAlert
|
<UAlert
|
||||||
v-if="result.success"
|
v-if="result.success"
|
||||||
|
|
@ -359,7 +376,8 @@
|
||||||
variant="soft"
|
variant="soft"
|
||||||
:title="'Success looks like:'"
|
:title="'Success looks like:'"
|
||||||
:description="result.success"
|
:description="result.success"
|
||||||
class="mb-6" />
|
class="mb-6"
|
||||||
|
/>
|
||||||
|
|
||||||
<UCard v-if="result.alternatives" class="bg-neutral-50">
|
<UCard v-if="result.alternatives" class="bg-neutral-50">
|
||||||
<h3 class="font-semibold text-neutral-900 mb-4 text-lg">
|
<h3 class="font-semibold text-neutral-900 mb-4 text-lg">
|
||||||
|
|
@ -369,7 +387,8 @@
|
||||||
<UCard
|
<UCard
|
||||||
v-for="alt in result.alternatives"
|
v-for="alt in result.alternatives"
|
||||||
:key="alt.method"
|
:key="alt.method"
|
||||||
class="bg-white">
|
class="bg-white"
|
||||||
|
>
|
||||||
<span class="font-semibold">{{ alt.method }}:</span>
|
<span class="font-semibold">{{ alt.method }}:</span>
|
||||||
{{ alt.when }}
|
{{ alt.when }}
|
||||||
</UCard>
|
</UCard>
|
||||||
|
|
@ -380,10 +399,7 @@
|
||||||
<UButton @click="resetForm" color="violet">
|
<UButton @click="resetForm" color="violet">
|
||||||
Try Another Decision
|
Try Another Decision
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton @click="printResult" variant="outline" color="violet">
|
||||||
@click="printResult"
|
|
||||||
variant="outline"
|
|
||||||
color="violet">
|
|
||||||
Print Recommendation
|
Print Recommendation
|
||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -395,17 +411,16 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Export Options at Bottom -->
|
<!-- Export Options at Bottom -->
|
||||||
<div class="flex justify-center py-6">
|
|
||||||
<ExportOptions
|
<ExportOptions
|
||||||
:export-data="exportData"
|
:export-data="exportData"
|
||||||
filename="decision-framework"
|
filename="decision-framework"
|
||||||
title="Decision Framework Helper" />
|
title="Decision Framework Helper"
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ExportOptions from '~/components/ExportOptions.vue'
|
import ExportOptions from "~/components/ExportOptions.vue";
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
urgency: 3,
|
urgency: 3,
|
||||||
|
|
@ -584,8 +599,7 @@ function determineFramework() {
|
||||||
"Execute without delay",
|
"Execute without delay",
|
||||||
"Debrief when crisis passes",
|
"Debrief when crisis passes",
|
||||||
],
|
],
|
||||||
warning:
|
warning: "Only use in true emergencies. Follow up with team discussion afterward.",
|
||||||
"Only use in true emergencies. Follow up with team discussion afterward.",
|
|
||||||
success:
|
success:
|
||||||
"Crisis averted through quick action. Team understands why autocratic mode was necessary.",
|
"Crisis averted through quick action. Team understands why autocratic mode was necessary.",
|
||||||
};
|
};
|
||||||
|
|
@ -621,11 +635,7 @@ function determineFramework() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AVOIDANT - non-urgent + undefined + low investment
|
// AVOIDANT - non-urgent + undefined + low investment
|
||||||
if (
|
if (state.urgency <= 2 && state.options === "undefined" && state.investment === "low") {
|
||||||
state.urgency <= 2 &&
|
|
||||||
state.options === "undefined" &&
|
|
||||||
state.investment === "low"
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
method: "Strategic Delay",
|
method: "Strategic Delay",
|
||||||
tagline: "Wait for clarity to emerge",
|
tagline: "Wait for clarity to emerge",
|
||||||
|
|
@ -638,10 +648,8 @@ function determineFramework() {
|
||||||
"Revisit when conditions change",
|
"Revisit when conditions change",
|
||||||
"Document why you're waiting",
|
"Document why you're waiting",
|
||||||
],
|
],
|
||||||
warning:
|
warning: "Don't let avoidance become paralysis. Set a deadline for revisiting.",
|
||||||
"Don't let avoidance become paralysis. Set a deadline for revisiting.",
|
success: "By waiting, better options emerged or the decision became unnecessary.",
|
||||||
success:
|
|
||||||
"By waiting, better options emerged or the decision became unnecessary.",
|
|
||||||
alternatives: [
|
alternatives: [
|
||||||
{
|
{
|
||||||
method: "Time-boxed exploration",
|
method: "Time-boxed exploration",
|
||||||
|
|
@ -752,8 +760,7 @@ function determineFramework() {
|
||||||
"Document all input received",
|
"Document all input received",
|
||||||
"Explain how input influenced the decision",
|
"Explain how input influenced the decision",
|
||||||
],
|
],
|
||||||
success:
|
success: "Decision informed by diverse perspectives with clear accountability.",
|
||||||
"Decision informed by diverse perspectives with clear accountability.",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -815,10 +822,7 @@ function determineFramework() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEMOCRATIC VOTE - larger group, time pressure
|
// DEMOCRATIC VOTE - larger group, time pressure
|
||||||
if (
|
if ((state.teamSize === "6-8" || state.teamSize === "9+") && state.urgency >= 4) {
|
||||||
(state.teamSize === "6-8" || state.teamSize === "9+") &&
|
|
||||||
state.urgency >= 4
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
method: "Democratic Vote",
|
method: "Democratic Vote",
|
||||||
tagline: "Majority decides, move forward together",
|
tagline: "Majority decides, move forward together",
|
||||||
|
|
@ -838,8 +842,7 @@ function determineFramework() {
|
||||||
],
|
],
|
||||||
warning:
|
warning:
|
||||||
"Don't vote on everything! Reserve it for when other methods are too slow.",
|
"Don't vote on everything! Reserve it for when other methods are too slow.",
|
||||||
success:
|
success: "Clear decision made efficiently with everyone having equal say.",
|
||||||
"Clear decision made efficiently with everyone having equal say.",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -940,7 +943,7 @@ const exportData = computed(() => ({
|
||||||
state: state,
|
state: state,
|
||||||
currentStep: currentStep.value,
|
currentStep: currentStep.value,
|
||||||
showResult: showResult.value,
|
showResult: showResult.value,
|
||||||
result: result.value
|
result: result.value,
|
||||||
},
|
},
|
||||||
surveyResponses: {
|
surveyResponses: {
|
||||||
urgency: state.urgency,
|
urgency: state.urgency,
|
||||||
|
|
@ -949,19 +952,19 @@ const exportData = computed(() => ({
|
||||||
impact: state.impact,
|
impact: state.impact,
|
||||||
options: state.options,
|
options: state.options,
|
||||||
investment: state.investment,
|
investment: state.investment,
|
||||||
teamSize: state.teamSize
|
teamSize: state.teamSize,
|
||||||
},
|
},
|
||||||
recommendedFramework: result.value || null,
|
recommendedFramework: result.value || null,
|
||||||
metadata: {
|
metadata: {
|
||||||
completedAt: showResult.value ? new Date().toISOString() : null,
|
completedAt: showResult.value ? new Date().toISOString() : null,
|
||||||
totalSteps: totalSteps,
|
totalSteps: totalSteps,
|
||||||
progressPercentage: Math.round((currentStep.value / totalSteps) * 100)
|
progressPercentage: Math.round((currentStep.value / totalSteps) * 100),
|
||||||
},
|
},
|
||||||
exportedAt: new Date().toISOString(),
|
exportedAt: new Date().toISOString(),
|
||||||
section: "decision-framework",
|
section: "decision-framework",
|
||||||
title: "Decision Framework Helper",
|
title: "Decision Framework Helper",
|
||||||
description: "Interactive wizard to find the right way to decide together"
|
description: "Interactive wizard to find the right way to decide together",
|
||||||
}))
|
}));
|
||||||
|
|
||||||
// Keyboard navigation
|
// Keyboard navigation
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue