Figure out router pattern for compliance steps
This commit is contained in:
parent
20614acb86
commit
4faa7fa8c0
8 changed files with 132 additions and 39 deletions
|
|
@ -32,22 +32,6 @@
|
|||
{{ end }}
|
||||
{{ define "content" }}
|
||||
<div class="container-fluid px-3 py-3">
|
||||
<!-- Header -->
|
||||
<header class="text-center mb-4 pb-3 border-bottom">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<img
|
||||
src="{{ .District.URLLogo }}"
|
||||
alt="{{ .District.Name }} logo"
|
||||
class="me-2"
|
||||
style="height: 40px; width: auto;"
|
||||
/>
|
||||
<h1 class="h5 mb-0">{{ .District.Name }}</h1>
|
||||
</div>
|
||||
<div class="text-muted small">
|
||||
<i class="bi bi-telephone"></i> {{ .District.OfficePhone }}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
|
|
|
|||
24
ts/rmo/components/HeaderCompliance.vue
Normal file
24
ts/rmo/components/HeaderCompliance.vue
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<header class="text-center mb-4 pb-3 border-bottom">
|
||||
<div class="d-flex align-items-center justify-content-center mb-2">
|
||||
<img
|
||||
:src="district.url_logo"
|
||||
:alt="district.name + ' logo'"
|
||||
class="me-2"
|
||||
style="height: 40px; width: auto"
|
||||
/>
|
||||
<h1 class="h5 mb-0">{{ district.name }}</h1>
|
||||
</div>
|
||||
<div class="text-muted small" v-if="district.phone_office">
|
||||
<i class="bi bi-telephone"></i> {{ district.phone_office }}
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { District } from "@/type/api";
|
||||
interface Props {
|
||||
district: District;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
</script>
|
||||
24
ts/rmo/components/ProgressBarCompliance.vue
Normal file
24
ts/rmo/components/ProgressBarCompliance.vue
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="small text-muted">Step {{ step }} of {{ maxSteps }}</span>
|
||||
</div>
|
||||
<div class="progress" style="height: 8px">
|
||||
<div
|
||||
class="progress-bar"
|
||||
role="progressbar"
|
||||
:style="{ width: (step / maxSteps) * 100 + '%' }"
|
||||
aria-valuenow="12"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
step: number;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
const maxSteps = 8;
|
||||
</script>
|
||||
|
|
@ -612,12 +612,13 @@ onMounted(() => {
|
|||
locationStore
|
||||
.get()
|
||||
.then((loc: GeolocationPosition) => {
|
||||
console.log("user geolocation", loc);
|
||||
const coords = loc.coords;
|
||||
currentLocation.value = coords;
|
||||
if (currentCamera.value) {
|
||||
currentCamera.value.location = coords;
|
||||
currentCamera.value.zoom = 15;
|
||||
}
|
||||
currentCamera.value = {
|
||||
location: coords,
|
||||
zoom: 15,
|
||||
};
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log("failed to get location", e);
|
||||
|
|
|
|||
58
ts/rmo/content/compliance/Address.vue
Normal file
58
ts/rmo/content/compliance/Address.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<div class="container-fluid px-3 py-3">
|
||||
<HeaderCompliance :district="district" />
|
||||
<!-- Progress Bar -->
|
||||
<ProgressBarCompliance :step="2" />
|
||||
<main>
|
||||
<h2 class="h4 mb-3">Confirm the property address</h2>
|
||||
|
||||
<p class="text-muted mb-4">
|
||||
Please enter the address so we can match your response with our records.
|
||||
</p>
|
||||
|
||||
<form id="address-form" method="POST" action="/compliance/address">
|
||||
<div class="mb-4">
|
||||
<label for="address-input" class="form-label fw-semibold">
|
||||
Property Address
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control form-control-lg"
|
||||
id="address-input"
|
||||
name="address"
|
||||
placeholder="Start typing your address..."
|
||||
autocomplete="off"
|
||||
data-autocomplete="true"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
Begin typing and select your address from the suggestions
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Map Placeholder -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold">Location Preview</label>
|
||||
<div class="map-placeholder" id="map-container">
|
||||
<span>Map will appear here after address is selected</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons -->
|
||||
<div class="d-flex gap-2 mt-4">
|
||||
<a class="btn btn-outline-secondary" href="../compliance"> Back </a>
|
||||
<a class="btn btn-primary flex-grow-1" href="concern"> Continue </a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { District } from "@/type/api";
|
||||
import HeaderCompliance from "@/rmo/components/HeaderCompliance.vue";
|
||||
import ProgressBarCompliance from "@/rmo/components/ProgressBarCompliance.vue";
|
||||
interface Props {
|
||||
district: District;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
</script>
|
||||
|
|
@ -1,22 +1,7 @@
|
|||
<template>
|
||||
<div class="container-fluid px-3 py-3">
|
||||
<HeaderCompliance :district="district" />
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="small text-muted">Step 1 of 8</span>
|
||||
</div>
|
||||
<div class="progress" style="height: 8px">
|
||||
<div
|
||||
class="progress-bar"
|
||||
role="progressbar"
|
||||
style="width: 12%"
|
||||
aria-valuenow="12"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<ProgressBarCompliance :step="2" />
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
|
|
@ -35,7 +20,7 @@
|
|||
</div>
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
<RouterLink class="btn btn-primary btn-lg" to="./address">
|
||||
<RouterLink class="btn btn-primary btn-lg" to="./compliance/address">
|
||||
Get Started</RouterLink
|
||||
>
|
||||
</div>
|
||||
|
|
@ -45,6 +30,7 @@
|
|||
<script setup lang="ts">
|
||||
import type { District } from "@/type/api";
|
||||
import HeaderCompliance from "@/rmo/components/HeaderCompliance.vue";
|
||||
import ProgressBarCompliance from "@/rmo/components/ProgressBarCompliance.vue";
|
||||
interface Props {
|
||||
district: District;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import Compliance from "@/rmo/view/Compliance.vue";
|
||||
import ComplianceAddress from "@/rmo/content/compliance/Address.vue";
|
||||
import ComplianceIntro from "@/rmo/content/compliance/Intro.vue";
|
||||
import HomeBase from "@/rmo/view/Home.vue";
|
||||
import HomeDistrict from "@/rmo/view/district/Home.vue";
|
||||
import NuisanceBase from "@/rmo/view/Nuisance.vue";
|
||||
|
|
@ -27,9 +29,21 @@ const routes: RouteRecordRaw[] = [
|
|||
props: true,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
component: ComplianceIntro,
|
||||
name: "ComplianceIntro",
|
||||
path: "",
|
||||
},
|
||||
{
|
||||
component: ComplianceAddress,
|
||||
name: "ComplianceAddress",
|
||||
path: "address",
|
||||
},
|
||||
],
|
||||
component: Compliance,
|
||||
path: "/district/:slug/compliance",
|
||||
name: "Compliance",
|
||||
component: Compliance,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ body > .container-fluid {
|
|||
</style>
|
||||
<template>
|
||||
<template v-if="district">
|
||||
<Intro :district="district" />
|
||||
<router-view v-slot="{ Component }">
|
||||
<component :is="Component" :district="district" />
|
||||
</router-view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>loading {{ slug }}...</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue