Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
02d7bdb
the page exists but there is a reloading problem
Deethya0715 Feb 16, 2026
ed89c97
reload is still not working, and the modal is not showing up properly
Deethya0715 Feb 16, 2026
4dc3221
removed the extra banner
Deethya0715 Feb 16, 2026
2651801
now the entire banner is removed
Deethya0715 Feb 16, 2026
88fa3e1
actual base of form is complete
Deethya0715 Feb 16, 2026
82ba075
colors look good now!!!!
Deethya0715 Feb 16, 2026
f070401
it is finished!!!!!!!!!!!
Deethya0715 Feb 16, 2026
4692e74
added the new form order
Deethya0715 Feb 16, 2026
787f341
working on the new form and working on the pdf converter
Deethya0715 Feb 17, 2026
be6e22a
db notes
Deethya0715 Feb 17, 2026
5170e2a
Revert "working on the new form and working on the pdf converter"
Deethya0715 Feb 17, 2026
f8db132
Revert "it is finished!!!!!!!!!!!"
Deethya0715 Feb 17, 2026
c9d0003
Color inspo?
Deethya0715 Feb 18, 2026
eff9132
added the logo to file directory
Deethya0715 Feb 19, 2026
95ef00e
added the logo but it loooks terrible in dark mode, cuz text is black
Deethya0715 Feb 19, 2026
2807848
removed the extra nav bar
Deethya0715 Feb 19, 2026
a8864f1
the reloading this is finally working now!!!!!!!!!
Deethya0715 Feb 19, 2026
37d9438
now the double header is gone not earlier
Deethya0715 Feb 19, 2026
2de0718
made the logo a little bit bigger
Deethya0715 Feb 19, 2026
c3a1972
cahnged the colors
Deethya0715 Feb 19, 2026
209dac8
removed the extra navbars
Deethya0715 Feb 20, 2026
d12c479
answer choices are vertical
Deethya0715 Feb 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"prisma.pinToPrisma6": false
}
8 changes: 8 additions & 0 deletions app/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default defineAppConfig({
ui: {
colors: {
primary: 'primary',
neutral: 'slate',
},
},
})
65 changes: 49 additions & 16 deletions app/app.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,66 @@
<script setup lang="ts">
const colorMode = useColorMode()
import { authClient } from './utils/auth-client'

const isDark = computed({
get () {
return colorMode.value === 'dark'
},
set () {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
const colorMode = useColorMode()

const isDark = computed({
get() {
return colorMode.value === 'dark'
},
set() {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
},
})

async function logout() {
await authClient.signOut()
await navigateTo('/auth', { external: true })
}
})
</script>

<template>
<UApp>
<div class="min-h-screen flex flex-col bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
<header class="border-b border-gray-200 dark:border-gray-800 bg-white/75 dark:bg-gray-900/75 backdrop-blur-md sticky top-0 z-50">
<UContainer class="flex items-center justify-between h-16">
<NuxtLink to="/" class="text-xl font-bold flex items-center gap-2">
<UIcon name="i-heroicons-cube-transparent" class="w-8 h-8 text-primary-500" />
<span>Nuxt Template</span>
<div
class="flex min-h-screen flex-col bg-white text-[#21364B] transition-colors duration-300 dark:bg-gray-900 dark:text-[#F9F3D9]"
>
<header
class="sticky top-0 z-50 border-b border-gray-200 bg-white/75 backdrop-blur-md dark:border-gray-700 dark:bg-gray-900/75"
>
<UContainer class="flex h-16 items-center justify-between">
<NuxtLink to="/" class="flex items-center gap-2 text-xl font-bold">
<img src="/hopecopeheallogo.png" alt="Hope. Cope. Heal." class="h-14 w-auto dark:rounded-md dark:bg-white dark:px-3 dark:py-1" />
</NuxtLink>


<nav class="flex items-center gap-4">
<NuxtLink
to="/"
class="text-sm font-medium text-gray-600 hover:text-[#21364B] dark:text-gray-400 dark:hover:text-[#F9F3D9]"
>
Dashboard
</NuxtLink>
<NuxtLink
to="/tasks"
class="text-sm font-medium text-gray-600 hover:text-[#21364B] dark:text-gray-400 dark:hover:text-[#F9F3D9]"
>
Tasks
</NuxtLink>
</nav>

<div class="flex items-center gap-2">
<UButton
:icon="isDark ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
color="neutral"
variant="ghost"
@click="isDark = !isDark"
aria-label="Toggle Theme"
@click="isDark = !isDark"
/>
<UButton
color="neutral"
variant="ghost"
size="sm"
icon="i-heroicons-arrow-right-on-rectangle-20-solid"
label="Logout"
@click="logout"
/>
</div>
</UContainer>
Expand Down
21 changes: 21 additions & 0 deletions app/assets/css/main.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
@import "tailwindcss";
@import "@nuxt/ui";

/* ── Primary: slate blue #4A6274 (both modes) ───────────────── */
@theme {
--color-primary-50: #eef2f5;
--color-primary-100: #d9e4ea;
--color-primary-200: #b3c9d5;
--color-primary-300: #8aafc0;
--color-primary-400: #6594ab;
--color-primary-500: #4a6274;
--color-primary-600: #3d5262;
--color-primary-700: #2f3f4d;
--color-primary-800: #21364b;
--color-primary-900: #1b2b3c;
--color-primary-950: #0f1921;
}

/* ── Dark mode: shift primary lighter for contrast ──────────── */
.dark {
--color-primary-400: #8aafc0;
--color-primary-500: #6594ab;
--color-primary-600: #4a6274;
}
206 changes: 206 additions & 0 deletions app/components/FormPageContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<script setup lang="ts">
const props = defineProps<{ slug: string }>()
const slugRef = computed(() => props.slug)
const {
form,
formPending,
formError,
formStatus,
slug,
responses,
completedCount,
totalCount,
progressPercent,
setResponse,
submitting,
submitError,
showIncompleteBanner,
unansweredCount,
dismissIncompleteBanner,
submit,
} = await useFormBySlug(slugRef)
</script>

<style scoped>
.float-enter-active,
.float-leave-active {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.float-enter-from,
.float-leave-to {
opacity: 0;
transform: translateY(0.5rem);
}
</style>

<template>
<div class="min-h-screen bg-gray-50 dark:bg-gray-950">
<div
v-if="form"
class="border-b border-gray-200 bg-white/95 px-4 py-3 sm:px-6 dark:border-gray-700 dark:bg-gray-900/95"
>
<div class="mx-auto max-w-3xl">
<div class="flex items-center justify-between text-sm">
<span class="font-medium text-gray-700 dark:text-gray-300"
>{{ progressPercent }}% Complete</span
>
<span class="text-gray-500 dark:text-gray-400"
>{{ completedCount }} of {{ totalCount }} answered</span
>
</div>
<div class="mt-2 h-2 w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700">
<div
class="bg-primary-500 h-full rounded-full transition-all duration-300"
:style="{ width: `${progressPercent}%` }"
/>
</div>
</div>
</div>

<main class="mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
<div v-if="formPending" class="space-y-6">
<USkeleton class="h-8 w-2/3" />
<USkeleton class="h-4 w-full" />
<USkeleton v-for="i in 5" :key="i" class="h-20 w-full" />
</div>

<UAlert
v-else-if="formError || !slug"
icon="i-heroicons-exclamation-triangle-20-solid"
color="error"
variant="subtle"
title="Form not found"
:description="
formError?.message || 'Invalid form URL. Please check the link and try again.'
"
>
<template #actions>
<UButton to="/tasks" variant="outline" size="sm"> Go to Tasks </UButton>
</template>
</UAlert>

<template v-else-if="form">
<div class="mb-8">
<h1 class="text-2xl font-bold tracking-tight text-[#21364B] sm:text-3xl dark:text-[#F9F3D9]">
{{ form.title }}
</h1>
<p v-if="form.description" class="mt-2 text-gray-600 dark:text-gray-400">
{{ form.description }}
</p>
<UAlert
v-if="formStatus?.isCompleted"
color="info"
variant="subtle"
title="Editing Completed Form"
description="You are editing a previously completed form. Your changes will update your results."
class="mt-4"
/>
</div>

<form class="space-y-8" @submit.prevent="submit">
<div
v-if="form.slug === 'ace-form'"
class="border-primary-200 bg-primary-50 dark:border-primary-800 dark:bg-primary-900/20 mb-6 rounded-lg border p-4"
>
<p class="text-primary-900 dark:text-primary-200 text-sm font-medium">
While you were growing up, during your first 18 years of life:
</p>
</div>

<div
v-for="(q, index) in form.questions"
:key="q.id"
class="rounded-xl border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-900"
>
<fieldset>
<legend class="text-base font-medium text-[#21364B] dark:text-[#F9F3D9]">
{{ Number(index) + 1 }}. {{ q.text }}
</legend>
<div v-if="q.type === 'radio'" class="mt-4 flex flex-col gap-2">
<label
v-for="opt in ['Yes', 'No']"
:key="opt"
class="focus-within:ring-primary-500 relative flex cursor-pointer items-center rounded-lg border px-4 py-3 transition focus-within:ring-2"
:class="
responses[q.alias] === opt
? 'border-primary-500 bg-primary-50 dark:border-primary-600 dark:bg-primary-900/20'
: 'border-gray-200 hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600'
"
>
<input
type="radio"
:name="q.alias"
:value="opt"
:checked="responses[q.alias] === opt"
class="sr-only"
@change="setResponse(q.alias, opt)"
/>
<span class="text-sm font-medium text-[#21364B] dark:text-[#F9F3D9]">{{ opt }}</span>
</label>
</div>
<div v-else class="mt-4">
<input
:value="responses[q.alias]"
type="text"
:name="q.alias"
class="focus:border-primary-500 focus:ring-primary-500 w-full rounded-lg border border-gray-300 bg-[#F9F3D9] px-4 py-2.5 text-[#21364B] shadow-sm dark:border-gray-700 dark:bg-gray-800 dark:text-[#F9F3D9]"
placeholder="Your answer"
@input="setResponse(q.alias, ($event.target as HTMLInputElement).value)"
/>
</div>
</fieldset>
</div>

<UAlert
v-if="submitError"
color="error"
variant="subtle"
:title="submitError"
class="mb-4"
/>

<div class="flex justify-end gap-3">
<UButton
type="submit"
size="lg"
:loading="submitting"
:disabled="submitting"
@click.prevent="submit"
>
Submit
</UButton>
</div>
</form>
</template>
</main>

<!-- Floating box: incomplete form info after submit attempt -->
<Transition name="float">
<div
v-if="form && showIncompleteBanner && unansweredCount > 0"
class="fixed bottom-6 right-6 z-50 flex max-w-sm items-start gap-3 rounded-xl border border-amber-200 bg-white p-4 shadow-lg dark:border-amber-800 dark:bg-gray-900"
>
<UIcon
name="i-heroicons-exclamation-circle-20-solid"
class="mt-0.5 h-5 w-5 shrink-0 text-amber-500"
/>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium text-[#21364B] dark:text-[#F9F3D9]">Form incomplete</p>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
You have
<span class="font-semibold text-amber-600 dark:text-amber-400">{{ unansweredCount }}</span>
{{ unansweredCount === 1 ? 'question' : 'questions' }} left ({{ totalCount }} total).
</p>
</div>
<button
type="button"
aria-label="Dismiss"
class="shrink-0 rounded p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300"
@click="dismissIncompleteBanner"
>
<UIcon name="i-heroicons-x-mark-20-solid" class="h-4 w-4" />
</button>
</div>
</Transition>
</div>
</template>
Loading