mirror of
https://github.com/grassrootseconomics/farmstar-survey-ui.git
synced 2024-12-05 00:16:10 +01:00
init: farmstar-survey-ui
This commit is contained in:
commit
2ff68432a2
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
37
README.md
Normal file
37
README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# FarmStar Survey UI
|
||||||
|
|
||||||
|
## Required env variables
|
||||||
|
|
||||||
|
- `BASE_URL`
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run preview
|
||||||
|
```
|
22
app.vue
Normal file
22
app.vue
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<AppNavbar />
|
||||||
|
<div class="bg-gray-100">
|
||||||
|
<div class="max-w-screen-xl mx-auto">
|
||||||
|
<NuxtPage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
useHead({
|
||||||
|
title: "FarmStar Survey",
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* You can keep or remove the body style depending on your preference */
|
||||||
|
body {
|
||||||
|
background-color: #f3f4f6; /* You can use the color code for light grey */
|
||||||
|
margin: 0; /* Remove default body margin */
|
||||||
|
}
|
||||||
|
</style>
|
3
assets/css/input.css
Normal file
3
assets/css/input.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
72
components/App/AppNavbar.vue
Normal file
72
components/App/AppNavbar.vue
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<nav class="border-gray-200 bg-gray-900">
|
||||||
|
<div
|
||||||
|
class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"
|
||||||
|
>
|
||||||
|
<NuxtLink to="/" class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||||
|
<span
|
||||||
|
class="self-center text-2xl font-semibold whitespace-nowrap text-white"
|
||||||
|
>FarmStar Survey</span
|
||||||
|
></NuxtLink
|
||||||
|
>
|
||||||
|
|
||||||
|
<button
|
||||||
|
@click="toggleMenu"
|
||||||
|
data-collapse-toggle="navbar-default"
|
||||||
|
type="button"
|
||||||
|
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm rounded-lg md:hidden focus:outline-none focus:ring-2 text-gray-400 hover:bg-gray-700 focus:ring-gray-600"
|
||||||
|
aria-controls="navbar-default"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Open main menu</span>
|
||||||
|
<svg
|
||||||
|
class="w-5 h-5"
|
||||||
|
aria-hidden="true"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 17 14"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M1 1h15M1 7h15M1 13h15"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
:class="{ hidden: !isMenuOpen, 'lg:flex': isMenuOpen }"
|
||||||
|
class="w-full md:block md:w-auto"
|
||||||
|
id="navbar-default"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="font-medium flex flex-col p-4 md:p-0 mt-4 border rounded-lg md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 bg-gray-900 border-gray-700"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<NuxtLink
|
||||||
|
to="/about"
|
||||||
|
class="block py-2 px-3 rounded md:border-0 md:p-0 text-white md:hover:text-blue-500 hover:bg-gray-700 hover:text-white md:hover:bg-transparent"
|
||||||
|
>About</NuxtLink
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<NuxtLink
|
||||||
|
to="/help"
|
||||||
|
class="block py-2 px-3 rounded md:border-0 md:p-0 text-white md:hover:text-blue-500 hover:bg-gray-700 hover:text-white md:hover:bg-transparent"
|
||||||
|
>Help</NuxtLink
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const isMenuOpen = ref(false);
|
||||||
|
|
||||||
|
const toggleMenu = () => {
|
||||||
|
isMenuOpen.value = !isMenuOpen.value;
|
||||||
|
};
|
||||||
|
</script>
|
15
components/Card.vue
Normal file
15
components/Card.vue
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="bg-white mx-2 p-4 rounded border border-gray-300 mb-4 md:min-w-[250px] md:w-full md:mx-0 lg:mx-4"
|
||||||
|
>
|
||||||
|
<h2 class="text-l font-bold mb-2">{{ title }}</h2>
|
||||||
|
<p class="text-sm text-gray-600 mb-4">{{ subtitle }}</p>
|
||||||
|
<NuxtLink :to="link">
|
||||||
|
<button class="bg-blue-500 text-white px-4 py-2 rounded">Open</button>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps(["title", "subtitle", "link"]);
|
||||||
|
</script>
|
5
components/FormSheet.vue
Normal file
5
components/FormSheet.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bg-white rounded border border-gray-300 p-3">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
28
components/Notice.vue
Normal file
28
components/Notice.vue
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
id="alert-additional-content-1"
|
||||||
|
class="p-4 mb-4 text-blue-800 border border-blue-300 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400 dark:border-blue-800"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg
|
||||||
|
class="flex-shrink-0 w-4 h-4 me-2"
|
||||||
|
aria-hidden="true"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="sr-only">Info</span>
|
||||||
|
<h3 class="text-lg font-medium">Info</h3>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 text-sm">{{ subtitle }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps(["subtitle"]);
|
||||||
|
</script>
|
51
components/SuccessAlert.vue
Normal file
51
components/SuccessAlert.vue
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
id="alert-additional-content-3"
|
||||||
|
class="p-4 mb-4 text-green-800 border border-green-300 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400 dark:border-green-800"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg
|
||||||
|
class="flex-shrink-0 w-4 h-4 me-2"
|
||||||
|
aria-hidden="true"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="sr-only">Info</span>
|
||||||
|
<h3 class="text-lg font-medium">{{ title }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-4 text-sm">
|
||||||
|
{{ subtitle }}
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<NuxtLink :to="link">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="text-white bg-green-800 hover:bg-green-900 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-xs px-3 py-1.5 me-2 text-center inline-flex items-center dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="me-2 h-3 w-3"
|
||||||
|
aria-hidden="true"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 14"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M10 0C4.612 0 0 5.336 0 7c0 1.742 3.546 7 10 7 6.454 0 10-5.258 10-7 0-1.664-4.612-7-10-7Zm0 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{{ action }}
|
||||||
|
</button>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps(["title", "subtitle", "link", "action"]);
|
||||||
|
</script>
|
5
nuxt.config.ts
Normal file
5
nuxt.config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
devtools: { enabled: false },
|
||||||
|
modules: [ '@nuxtjs/tailwindcss', '@vueform/nuxt'],
|
||||||
|
})
|
11459
package-lock.json
generated
Normal file
11459
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
package.json
Normal file
22
package.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "farmstar-suvey-ui",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"dev:host": "nuxt dev --host",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nuxt/devtools": "latest",
|
||||||
|
"@nuxtjs/tailwindcss": "^6.10.0",
|
||||||
|
"@vueform/nuxt": "^1.4.0",
|
||||||
|
"flowbite": "^2.2.0",
|
||||||
|
"nuxt": "^3.8.2",
|
||||||
|
"vue": "^3.3.8",
|
||||||
|
"vue-router": "^4.2.5"
|
||||||
|
}
|
||||||
|
}
|
1
pages/about.vue
Normal file
1
pages/about.vue
Normal file
@ -0,0 +1 @@
|
|||||||
|
<template></template>
|
165
pages/distributor.vue
Normal file
165
pages/distributor.vue
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<template>
|
||||||
|
<div class="lg:flex items-start justify-center mt-4">
|
||||||
|
<FormSheet class="mx-2 mb-4 lg:w-3/4">
|
||||||
|
<ClientOnly>
|
||||||
|
<Vueform
|
||||||
|
v-if="!formSubmitted"
|
||||||
|
ref="form$"
|
||||||
|
validate-on="change"
|
||||||
|
:form-data="(form$) => form$.requestData"
|
||||||
|
@response="handleResponse"
|
||||||
|
endpoint="distributor"
|
||||||
|
>
|
||||||
|
<div class="text-xl mb-1 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">
|
||||||
|
Distributor onboarding survey
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TextElement
|
||||||
|
name="phone"
|
||||||
|
label="What is your primary phone number?"
|
||||||
|
description="Enter a valid Kenyan phone number starting with 07 or 01 that you registered with."
|
||||||
|
rules="required|phone"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="distributor_name"
|
||||||
|
label="What is the name of the agri-input distributor you work with?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
maraba_investments: 'Maraba Investments',
|
||||||
|
farmers_center: 'Farmers Center',
|
||||||
|
farmers_world: 'Farmers World',
|
||||||
|
farmers_desk: 'Farmers Desk',
|
||||||
|
mazao_na_afya: 'Mazao na Afya',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="type"
|
||||||
|
label="What types of fertilizers do you current stock at your distributor?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
synthetic: 'Synthetic/Chemical',
|
||||||
|
organic: 'Organic',
|
||||||
|
both: 'Both',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="synthetic_percentage"
|
||||||
|
label="In the past six months, what percentage of your fertilizer sales comprised synthetic fertilizers?"
|
||||||
|
description="Enter a percentage value"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
input-type="number"
|
||||||
|
:conditions="[['type', 'both']]"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="organic_percentage"
|
||||||
|
label="In the past six months, what percentage of your fertilizer sales comprised organic fertilizers?"
|
||||||
|
description="Enter a percentage value"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
input-type="number"
|
||||||
|
:conditions="[['type', 'both']]"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
name="synthetic_factors"
|
||||||
|
label="What factors do you believe influence farmers' preferences for synthetic fertilizers? (Select all that apply)"
|
||||||
|
:items="{
|
||||||
|
increased_crop_yield: 'Increased Crop Yield',
|
||||||
|
cost_effective: 'Cost-effectiveness',
|
||||||
|
ease_of_application: 'Ease of application',
|
||||||
|
availability: 'Availability',
|
||||||
|
marketing: 'Marketing/Advertising',
|
||||||
|
govt_incentives: 'Government Incentives',
|
||||||
|
other: 'Other',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['type', ['both', 'synthetic']]]"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
name="organic_factors"
|
||||||
|
label="What factors do you believe influence farmers' preferences for organic fertilizers? (Select all that apply)"
|
||||||
|
:items="{
|
||||||
|
increased_crop_yield: 'Increased Crop Yield',
|
||||||
|
cost_effective: 'Cost-effectiveness',
|
||||||
|
ease_of_application: 'Ease of application',
|
||||||
|
availability: 'Availability',
|
||||||
|
marketing: 'Marketing/Advertising',
|
||||||
|
govt_incentives: 'Government Incentives',
|
||||||
|
other: 'Other',
|
||||||
|
environmental_concerns: 'Environmental concerns',
|
||||||
|
soil_health: 'Soil health improvement',
|
||||||
|
consumer_demand: 'Consumer demand for organic produce',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['type', ['both', 'organic']]]"
|
||||||
|
/>
|
||||||
|
<TextareaElement
|
||||||
|
name="trends"
|
||||||
|
rules="required|max:250"
|
||||||
|
label="Have you noticed any specific trends or patterns in farmers' choices between synthetic and organic fertilizers?"
|
||||||
|
/>
|
||||||
|
<TextareaElement
|
||||||
|
name="obstacles"
|
||||||
|
rules="required|max:250"
|
||||||
|
:conditions="[['type', ['both', 'organic']]]"
|
||||||
|
label="Are there any obstacles faced in promoting or selling organic fertilizers compared to synthetic fertilizers? If yes, please specify."
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="need_education"
|
||||||
|
label="Do farmers express a need for more education or information about the benefits of organic fertilizers compared to synthetic ones?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['type', ['both', 'organic']]]"
|
||||||
|
/>
|
||||||
|
<TextareaElement
|
||||||
|
name="organic_strategies"
|
||||||
|
rules="required|max:250"
|
||||||
|
:conditions="[['type', ['both', 'organic']]]"
|
||||||
|
label="What strategies have been most effective in encouraging the adoption of organic fertilizers among walk-in farmers?"
|
||||||
|
/>
|
||||||
|
<TextareaElement
|
||||||
|
name="farmstar_strategies"
|
||||||
|
rules="required|max:500"
|
||||||
|
:conditions="[['type', ['both', 'organic']]]"
|
||||||
|
label="In your opinion, what strategies could Farm Star use to encourage an increased adoption of organic fertilizers among farmers?"
|
||||||
|
/>
|
||||||
|
<ButtonElement name="submit" add-class="mt-2" submits>
|
||||||
|
Submit
|
||||||
|
</ButtonElement>
|
||||||
|
</Vueform>
|
||||||
|
<SuccessAlert
|
||||||
|
v-else
|
||||||
|
title="Submission Successful"
|
||||||
|
subtitle="Thank you for submitting the form."
|
||||||
|
link="/"
|
||||||
|
action="Home"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</FormSheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const form$ = ref(null);
|
||||||
|
const formSubmitted = ref(false);
|
||||||
|
|
||||||
|
const handleResponse = async (response, form$) => {
|
||||||
|
if (response.status <= 201) {
|
||||||
|
formSubmitted.value = true;
|
||||||
|
} else {
|
||||||
|
form$.messageBag.append(response.data?.message);
|
||||||
|
if (Object.keys(response.data.data)[0]?.message) {
|
||||||
|
form$.messageBag.append(
|
||||||
|
Object.keys(response.data.data)[0] +
|
||||||
|
": " +
|
||||||
|
Object.values(response.data.data)[0]?.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
434
pages/farmer.vue
Normal file
434
pages/farmer.vue
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
<template>
|
||||||
|
<div class="lg:flex items-start justify-center mt-4">
|
||||||
|
<FormSheet class="mx-2 mb-4 lg:w-3/4">
|
||||||
|
<ClientOnly>
|
||||||
|
<Vueform
|
||||||
|
v-if="!formSubmitted"
|
||||||
|
ref="form$"
|
||||||
|
validate-on="change"
|
||||||
|
:form-data="(form$) => form$.requestData"
|
||||||
|
@response="handleResponse"
|
||||||
|
endpoint="farmer"
|
||||||
|
>
|
||||||
|
<div class="text-xl mb-1 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">
|
||||||
|
Farmer onboarding survey
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TextElement
|
||||||
|
name="phone"
|
||||||
|
label="What is your primary phone number?"
|
||||||
|
description="Enter a valid Kenyan phone number starting with 07 or 01 that you registered with."
|
||||||
|
rules="required|phone"
|
||||||
|
/>
|
||||||
|
<div class="text mb-1 mt-1 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">Farm Details</div>
|
||||||
|
</div>
|
||||||
|
<GroupElement name="farm_details">
|
||||||
|
<SelectElement
|
||||||
|
name="county"
|
||||||
|
label="What county are you located in?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
kirinyaga: 'Kirinyaga',
|
||||||
|
muranga: 'Muranga',
|
||||||
|
nakuru: 'Nakuru',
|
||||||
|
meru: 'Meru',
|
||||||
|
uasin_gishu: 'Uasin Gishu',
|
||||||
|
kajiado: 'Kajiado',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="sub_county"
|
||||||
|
label="What sub-county are you located in?"
|
||||||
|
rules="required|max:50"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="farming_area_acres"
|
||||||
|
input-type="number"
|
||||||
|
label="How many acres of land are you currently farming?"
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
name="planned_crops"
|
||||||
|
label="Which crops do you plan to grow in the coming season?"
|
||||||
|
:items="{
|
||||||
|
rice: 'Rice',
|
||||||
|
coffee: 'Coffee',
|
||||||
|
tea: 'Tea',
|
||||||
|
sugarcane: 'Sugarcane',
|
||||||
|
miraa: 'Miraa',
|
||||||
|
avocados: 'Avocados',
|
||||||
|
maize: 'Maize',
|
||||||
|
potatoes: 'Potatoes',
|
||||||
|
sorghum: 'Sorghum',
|
||||||
|
other_fruits: 'Other fruits',
|
||||||
|
other_vegetables: 'Other vegetables',
|
||||||
|
other_grains: 'Other grains',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
description="Select all options that apply."
|
||||||
|
/>
|
||||||
|
</GroupElement>
|
||||||
|
<div class="text mt-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">
|
||||||
|
Past Harvest Details
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12">
|
||||||
|
<Notice
|
||||||
|
subtitle="Select all the crops that you have planted in the last 3 years, the average harvest you have gotten (in kg/acre) and how much you have earned (in ksh/kg) on selling each crop."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ListElement
|
||||||
|
name="past_harvest_details"
|
||||||
|
label="Harvest details for the last 3 years"
|
||||||
|
:min="1"
|
||||||
|
>
|
||||||
|
<template #default="{ index }">
|
||||||
|
<p>Crop {{ index + 1 }}</p>
|
||||||
|
<ObjectElement :name="index">
|
||||||
|
<SelectElement
|
||||||
|
name="crop_type"
|
||||||
|
rules="required"
|
||||||
|
:search="true"
|
||||||
|
:items="{
|
||||||
|
rice: 'Rice',
|
||||||
|
coffee: 'Coffee',
|
||||||
|
tea: 'Tea',
|
||||||
|
sugarcane: 'Sugarcane',
|
||||||
|
miraa: 'Miraa',
|
||||||
|
avocados: 'Avocados',
|
||||||
|
maize: 'Maize',
|
||||||
|
potatoes: 'Potatoes',
|
||||||
|
sorghum: 'Sorghum',
|
||||||
|
other_fruits: 'Other fruits',
|
||||||
|
other_vegetables: 'Other vegetables',
|
||||||
|
other_grains: 'Other grains',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="average_harvest"
|
||||||
|
label="Average harvest"
|
||||||
|
description="Average yield/output in kg/acre."
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="average_earning"
|
||||||
|
label="Average earning"
|
||||||
|
description="Average yield/output in ksh/kg."
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<div class="col-span-12">
|
||||||
|
<div class="border-t border-gray-300 mt-1"></div>
|
||||||
|
</div>
|
||||||
|
</ObjectElement>
|
||||||
|
</template>
|
||||||
|
</ListElement>
|
||||||
|
<div class="text mt-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">
|
||||||
|
Budget and Expenditure Details
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TextElement
|
||||||
|
name="total_expenditure"
|
||||||
|
input-type="number"
|
||||||
|
label="On average, how much do you spend on seeds, fertilizers, and crop protection (herbicides, pesticides, etc.) for a year?"
|
||||||
|
description="Average in ksh. per year"
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<GroupElement name="expenditure_details">
|
||||||
|
<StaticElement
|
||||||
|
name="static"
|
||||||
|
description="Total percentage should add upto 100%"
|
||||||
|
>How would you say your budget is split between seeds,
|
||||||
|
fertilizers, and crop protection?</StaticElement
|
||||||
|
>
|
||||||
|
<TextElement
|
||||||
|
columns="4"
|
||||||
|
name="seeds_expenditure_percentage"
|
||||||
|
input-type="number"
|
||||||
|
label="Seeds %"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
columns="4"
|
||||||
|
name="fertilizer_expenditure_percentage"
|
||||||
|
input-type="number"
|
||||||
|
label="Fertilizer %"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
F
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
columns="4"
|
||||||
|
name="crops_protection_expenditure_percentage"
|
||||||
|
input-type="number"
|
||||||
|
label="Crops Protection %"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
/>
|
||||||
|
</GroupElement>
|
||||||
|
<GroupElement name="fertilizer_expenditure_details">
|
||||||
|
<StaticElement
|
||||||
|
name="static"
|
||||||
|
description="Total percentage should add upto 100%"
|
||||||
|
>How is your spend on fertilizers split between
|
||||||
|
synthetic/inorganic fertilizers (like DAP, NPK, etc.) and
|
||||||
|
organic/natural fertilizers (like manure, compost,
|
||||||
|
etc.)</StaticElement
|
||||||
|
>
|
||||||
|
<TextElement
|
||||||
|
columns="6"
|
||||||
|
name="synthetic_fertilizers_expenditure_percentage"
|
||||||
|
input-type="number"
|
||||||
|
label="Synthetic Fertilizers %"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
columns="6"
|
||||||
|
name="natural_fertilizers_expenditure_percentage"
|
||||||
|
input-type="number"
|
||||||
|
label="Natural Fertilizers %"
|
||||||
|
rules="required|min:0|numeric|max:100"
|
||||||
|
/>
|
||||||
|
</GroupElement>
|
||||||
|
|
||||||
|
<StaticElement
|
||||||
|
name="static"
|
||||||
|
description="You can add upto 3 expenses."
|
||||||
|
>Which input—seeds, fertilizers, or crop protection—has increased
|
||||||
|
the most in cost for you over the past 3 years?</StaticElement
|
||||||
|
>
|
||||||
|
<ListElement name="increased_expenses" :min="0">
|
||||||
|
<template #default="{ index }">
|
||||||
|
<p>Expense</p>
|
||||||
|
<ObjectElement :name="index">
|
||||||
|
<SelectElement
|
||||||
|
rules="required"
|
||||||
|
name="expense_type"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
fertilizers: 'Fertilizers',
|
||||||
|
seeds: 'Seeds',
|
||||||
|
crop_protection: 'Crop Protection',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
rules="required"
|
||||||
|
name="increased_expense_actions"
|
||||||
|
label="How have you dealt with the cost increase?"
|
||||||
|
:items="{
|
||||||
|
no_change: 'No Change',
|
||||||
|
cheap_alternative: 'Purchased and used cheaper alternative',
|
||||||
|
less_quantity: 'Purchased and used less quantity',
|
||||||
|
more_quantity: 'Purchased more',
|
||||||
|
other: 'Other',
|
||||||
|
}"
|
||||||
|
description="Select all options that apply."
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="expense_action_overall_effect"
|
||||||
|
label="Have these changes affected how much you harvest?"
|
||||||
|
:native="false"
|
||||||
|
rules="required"
|
||||||
|
:items="{
|
||||||
|
increased_yields: 'Increased yields',
|
||||||
|
no_change_yields: 'No change to yields',
|
||||||
|
decreased_yields: 'Decreased yields',
|
||||||
|
other: 'Other',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<div class="col-span-12">
|
||||||
|
<div class="border-t border-gray-300 mt-1"></div>
|
||||||
|
</div>
|
||||||
|
</ObjectElement>
|
||||||
|
</template>
|
||||||
|
</ListElement>
|
||||||
|
<div class="text mt-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">EverGrow</div>
|
||||||
|
</div>
|
||||||
|
<SelectElement
|
||||||
|
name="evergrow_past"
|
||||||
|
:native="false"
|
||||||
|
label="Have you used EverGrow before?"
|
||||||
|
rules="required"
|
||||||
|
:items="{
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="evergrow_first"
|
||||||
|
label="What year did you first begin using EverGrow?"
|
||||||
|
:conditions="[['evergrow_past', 'yes']]"
|
||||||
|
input-type="number"
|
||||||
|
rules="required|min:2018|numeric"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="evergrow_application"
|
||||||
|
label="What is your typical application rate of EverGrow?"
|
||||||
|
description="Average in kg/acre."
|
||||||
|
:conditions="[['evergrow_past', 'yes']]"
|
||||||
|
input-type="number"
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
name="evergrow_crops"
|
||||||
|
label="What crops have you seen the most success with using EverGrow?"
|
||||||
|
:items="{
|
||||||
|
rice: 'Rice',
|
||||||
|
coffee: 'Coffee',
|
||||||
|
tea: 'Tea',
|
||||||
|
sugarcane: 'Sugarcane',
|
||||||
|
miraa: 'Miraa',
|
||||||
|
avocados: 'Avocados',
|
||||||
|
maize: 'Maize',
|
||||||
|
potatoes: 'Potatoes',
|
||||||
|
sorghum: 'Sorghum',
|
||||||
|
other_fruits: 'Other fruits',
|
||||||
|
other_vegetables: 'Other vegetables',
|
||||||
|
other_grains: 'Other grains',
|
||||||
|
}"
|
||||||
|
:conditions="[['evergrow_past', 'yes']]"
|
||||||
|
description="Select all options that apply."
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
columns="12"
|
||||||
|
name="evergrow_yield"
|
||||||
|
input-type="number"
|
||||||
|
label="How much have your yields typically improved by when using EverGrow (vs. when not)?"
|
||||||
|
description="Enter a percentage value"
|
||||||
|
:conditions="[['evergrow_past', 'yes']]"
|
||||||
|
rules="required|min:0|max:100|numeric"
|
||||||
|
/>
|
||||||
|
<div class="text mt-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">Other Fertilizers</div>
|
||||||
|
</div>
|
||||||
|
<SelectElement
|
||||||
|
label="Do you use any other types of fertilizer on your land?"
|
||||||
|
name="other_fertilizers"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
yes: 'Yes',
|
||||||
|
no: 'No',
|
||||||
|
not_sure: 'Not Sure',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<StaticElement
|
||||||
|
:conditions="[['other_fertilizers', 'yes']]"
|
||||||
|
name="static"
|
||||||
|
description="You can add upto 3 other fertilizer types."
|
||||||
|
>Select all other fertilizer types that you have used in the
|
||||||
|
past?</StaticElement
|
||||||
|
>
|
||||||
|
<ListElement
|
||||||
|
name="other_fertilizers_details"
|
||||||
|
:conditions="[['other_fertilizers', 'yes']]"
|
||||||
|
rules="required"
|
||||||
|
>
|
||||||
|
<template #default="{ index }">
|
||||||
|
<p>Fertilizer</p>
|
||||||
|
<ObjectElement :name="index">
|
||||||
|
<SelectElement
|
||||||
|
rules="required"
|
||||||
|
name="other_fertilizer_type"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
synthetic: 'Synthetic Fertilizer',
|
||||||
|
commercial_organic: 'Commercial Organic Fertilizer',
|
||||||
|
self_made: 'Self-made fertilizer/manure',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="other_fertilizer_application"
|
||||||
|
input-type="number"
|
||||||
|
label="What is your typical application rate of this type of fertilizer?"
|
||||||
|
description="Average in kg/acre."
|
||||||
|
rules="required|min:1|numeric"
|
||||||
|
/>
|
||||||
|
<TagsElement
|
||||||
|
rules="required"
|
||||||
|
name="other_fertilizer_crops"
|
||||||
|
label="What crops have you seen the most success with using this type of fertilizer"
|
||||||
|
:items="{
|
||||||
|
rice: 'Rice',
|
||||||
|
coffee: 'Coffee',
|
||||||
|
tea: 'Tea',
|
||||||
|
sugarcane: 'Sugarcane',
|
||||||
|
miraa: 'Miraa',
|
||||||
|
avocados: 'Avocados',
|
||||||
|
maize: 'Maize',
|
||||||
|
potatoes: 'Potatoes',
|
||||||
|
sorghum: 'Sorghum',
|
||||||
|
other_fruits: 'Other fruits',
|
||||||
|
other_vegetables: 'Other vegetables',
|
||||||
|
other_grains: 'Other grains',
|
||||||
|
}"
|
||||||
|
description="Select all options that apply."
|
||||||
|
/>
|
||||||
|
<div class="col-span-12">
|
||||||
|
<div class="border-t border-gray-300 mt-1"></div>
|
||||||
|
</div>
|
||||||
|
</ObjectElement>
|
||||||
|
</template>
|
||||||
|
</ListElement>
|
||||||
|
<div class="text mt-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">
|
||||||
|
Fertilizer Purchase Details
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12">
|
||||||
|
<Notice
|
||||||
|
subtitle="This applies for all types of fertilizers you purchase including Evergrow. "
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<TagsElement
|
||||||
|
name="purchase_channels"
|
||||||
|
rules="required"
|
||||||
|
label="Where do you typically purchase your fertilizer from?"
|
||||||
|
:items="{
|
||||||
|
manufacturers: 'Direct from manufacturers',
|
||||||
|
distributors: 'Distributors',
|
||||||
|
resellers: 'Resellers',
|
||||||
|
farmers: 'Fellow farmers',
|
||||||
|
other: 'Other',
|
||||||
|
}"
|
||||||
|
description="Select all options that apply."
|
||||||
|
/>
|
||||||
|
<ButtonElement name="submit" add-class="mt-2" submits>
|
||||||
|
Submit
|
||||||
|
</ButtonElement>
|
||||||
|
</Vueform>
|
||||||
|
<SuccessAlert
|
||||||
|
v-else
|
||||||
|
title="Submission Successful"
|
||||||
|
subtitle="Thank you for submitting the form."
|
||||||
|
link="/"
|
||||||
|
action="Home"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</FormSheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const form$ = ref(null);
|
||||||
|
const formSubmitted = ref(false);
|
||||||
|
|
||||||
|
const handleResponse = async (response, form$) => {
|
||||||
|
if (response.status <= 201) {
|
||||||
|
formSubmitted.value = true;
|
||||||
|
} else {
|
||||||
|
form$.messageBag.append(response.data?.error);
|
||||||
|
if (Object.keys(response.data.data)[0]?.message) {
|
||||||
|
form$.messageBag.append(
|
||||||
|
Object.keys(response.data.data)[0] +
|
||||||
|
": " +
|
||||||
|
Object.values(response.data.data)[0]?.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
1
pages/help.vue
Normal file
1
pages/help.vue
Normal file
@ -0,0 +1 @@
|
|||||||
|
<template></template>
|
24
pages/index.vue
Normal file
24
pages/index.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mt-4 flex flex-col md:flex-row md:space-x-4">
|
||||||
|
<Card
|
||||||
|
title="Sign up"
|
||||||
|
subtitle="To join the FarmStar rewards program."
|
||||||
|
link="/registration"
|
||||||
|
/>
|
||||||
|
<Card
|
||||||
|
title="Farmer onboarding survey"
|
||||||
|
subtitle="Tell us about what and how you farm!"
|
||||||
|
link="/farmer"
|
||||||
|
/>
|
||||||
|
<Card
|
||||||
|
title="Distributor onboarding survey"
|
||||||
|
subtitle="Tell us about the agri-inputs you sell!"
|
||||||
|
link="/distributor"
|
||||||
|
/>
|
||||||
|
<Card
|
||||||
|
title="Record a purchase"
|
||||||
|
subtitle="Of EverGrow organic fertilizer."
|
||||||
|
link="/transaction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
94
pages/registration.vue
Normal file
94
pages/registration.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<div class="lg:flex items-start justify-center mt-4">
|
||||||
|
<FormSheet class="mx-2 lg:w-3/4">
|
||||||
|
<ClientOnly>
|
||||||
|
<Vueform
|
||||||
|
v-if="!formSubmitted"
|
||||||
|
ref="form$"
|
||||||
|
validate-on="change"
|
||||||
|
:form-data="(form$) => form$.requestData"
|
||||||
|
@response="handleResponse"
|
||||||
|
endpoint="registration"
|
||||||
|
>
|
||||||
|
<div class="text-xl mb-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">Sign up</div>
|
||||||
|
</div>
|
||||||
|
<GroupElement name="personal_information">
|
||||||
|
<TextElement
|
||||||
|
name="name"
|
||||||
|
label="What is your full name?"
|
||||||
|
rules="required|max:150"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="age_group"
|
||||||
|
:native="false"
|
||||||
|
label="How old are you?"
|
||||||
|
description="Select the age group you fall into."
|
||||||
|
:items="['20-29', '30-39', '40-49', '50-59', '60-69', '70+']"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="gender"
|
||||||
|
label="What is your gender?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
female: 'Female',
|
||||||
|
male: 'Male',
|
||||||
|
transgender: 'Transgender',
|
||||||
|
other: 'Other',
|
||||||
|
no_response: 'Prefer not to response',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="phone"
|
||||||
|
label="What is your primary phone number?"
|
||||||
|
description="Enter a valid Kenyan phone number starting with 07 or 01."
|
||||||
|
rules="required|phone"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="participant_type"
|
||||||
|
label="Are you a farmer or a distributor?"
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
farmer: 'Farmer',
|
||||||
|
distributor: 'Distributor',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
</GroupElement>
|
||||||
|
<ButtonElement name="submit" add-class="mt-2" submits>
|
||||||
|
Register
|
||||||
|
</ButtonElement>
|
||||||
|
</Vueform>
|
||||||
|
<SuccessAlert
|
||||||
|
v-else
|
||||||
|
title="Submission Successful"
|
||||||
|
subtitle="Registration details submitted successfully. Your survey account is pending approval."
|
||||||
|
link="/"
|
||||||
|
action="Home"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</FormSheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const form$ = ref(null);
|
||||||
|
const formSubmitted = ref(false);
|
||||||
|
|
||||||
|
const handleResponse = async (response, form$) => {
|
||||||
|
if (response.status <= 201) {
|
||||||
|
formSubmitted.value = true;
|
||||||
|
} else {
|
||||||
|
form$.messageBag.append(response.data?.message);
|
||||||
|
if (Object.keys(response.data.data)[0]?.message) {
|
||||||
|
form$.messageBag.append(
|
||||||
|
Object.keys(response.data.data)[0] +
|
||||||
|
": " +
|
||||||
|
Object.values(response.data.data)[0]?.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
126
pages/transaction.vue
Normal file
126
pages/transaction.vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="lg:flex items-start justify-center mt-4">
|
||||||
|
<FormSheet class="mx-2 lg:w-3/4">
|
||||||
|
<ClientOnly>
|
||||||
|
<Vueform
|
||||||
|
v-if="!formSubmitted"
|
||||||
|
ref="form$"
|
||||||
|
validate-on="change"
|
||||||
|
:form-data="(form$) => form$.requestData"
|
||||||
|
@response="handleResponse"
|
||||||
|
endpoint="transaction"
|
||||||
|
>
|
||||||
|
<div class="text-xl mb-4 col-span-12">
|
||||||
|
<div class="border-b border-gray-300 pb-2">Record a purchase</div>
|
||||||
|
</div>
|
||||||
|
<TextElement
|
||||||
|
name="phone"
|
||||||
|
label="What is your phone number?"
|
||||||
|
rules="required"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="tx"
|
||||||
|
:native="false"
|
||||||
|
label="Did you buy or sell EverGrow Organic Fertilizer?"
|
||||||
|
:items="{
|
||||||
|
buy: 'Buy',
|
||||||
|
sell: 'Sell',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<SelectElement
|
||||||
|
name="distributor_name"
|
||||||
|
label="Select the name of the distributor you purchased EverGrow from."
|
||||||
|
:native="false"
|
||||||
|
:items="{
|
||||||
|
maraba_investments: 'Maraba Investments',
|
||||||
|
farmers_center: 'Farmers Center',
|
||||||
|
farmers_world: 'Farmers World',
|
||||||
|
farmers_desk: 'Farmers Desk',
|
||||||
|
mazao_na_afya: 'Mazao na Afya',
|
||||||
|
}"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['tx', 'buy']]"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="buy"
|
||||||
|
label="Enter the phone number of the person you bought EverGrow from."
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['tx', 'buy']]"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="sell"
|
||||||
|
label="Enter the phone number of the customer you sold EverGrow to."
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['tx', 'sell']]"
|
||||||
|
/>
|
||||||
|
<DateElement
|
||||||
|
:min="new Date(2024, 0, 23)"
|
||||||
|
name="buy_date"
|
||||||
|
label="When did you make this purchase?"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['tx', 'buy']]"
|
||||||
|
/>
|
||||||
|
<DateElement
|
||||||
|
:min="new Date(2024, 0, 23)"
|
||||||
|
name="sell_date"
|
||||||
|
label="When did you make this sale?"
|
||||||
|
rules="required"
|
||||||
|
:conditions="[['tx', 'sell']]"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="evergrow_quantity"
|
||||||
|
label="How much EverGrow did you purchase?"
|
||||||
|
description="1x50kg bag of EverGrow = 1, 2 bags = 2, etc."
|
||||||
|
rules="required|numeric|min:1|max:20"
|
||||||
|
input-type="number"
|
||||||
|
:conditions="[['tx', 'buy']]"
|
||||||
|
/>
|
||||||
|
<TextElement
|
||||||
|
name="evergrow_quantity"
|
||||||
|
label="How much EverGrow did you sell?"
|
||||||
|
description="1x50kg bag of EverGrow = 1, 2 bags = 2, etc."
|
||||||
|
rules="required|numeric|min:1|max:20"
|
||||||
|
input-type="number"
|
||||||
|
:conditions="[['tx', 'sell']]"
|
||||||
|
/>
|
||||||
|
<TextareaElement
|
||||||
|
name="feedback"
|
||||||
|
:conditions="[['tx', ['sell', 'buy']]]"
|
||||||
|
rules="max:300"
|
||||||
|
label="Do you have any comments or feedback for FarmStar?"
|
||||||
|
/>
|
||||||
|
<ButtonElement name="submit" add-class="mt-2" submits>
|
||||||
|
Submit
|
||||||
|
</ButtonElement>
|
||||||
|
</Vueform>
|
||||||
|
<SuccessAlert
|
||||||
|
v-else
|
||||||
|
title="Submission Successful"
|
||||||
|
subtitle="Transaction details submitted successfully."
|
||||||
|
link="/"
|
||||||
|
action="Home"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</FormSheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const form$ = ref(null);
|
||||||
|
const formSubmitted = ref(false);
|
||||||
|
|
||||||
|
const handleResponse = async (response, form$) => {
|
||||||
|
if (response.status <= 201) {
|
||||||
|
formSubmitted.value = true;
|
||||||
|
} else {
|
||||||
|
form$.messageBag.append(response.data?.message);
|
||||||
|
if (Object.keys(response.data.data)[0]?.message) {
|
||||||
|
form$.messageBag.append(
|
||||||
|
Object.keys(response.data.data)[0] +
|
||||||
|
": " +
|
||||||
|
Object.values(response.data.data)[0]?.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
22
tailwind.config.js
Normal file
22
tailwind.config.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: [
|
||||||
|
"./components/**/*.{js,vue,ts}",
|
||||||
|
"./layouts/**/*.vue",
|
||||||
|
"./pages/**/*.vue",
|
||||||
|
"./plugins/**/*.{js,ts}",
|
||||||
|
"./nuxt.config.{js,ts}",
|
||||||
|
'./vueform.config.{js,ts}',
|
||||||
|
'./node_modules/@vueform/vueform/themes/tailwind/**/*.vue',
|
||||||
|
'./node_modules/@vueform/vueform/themes/tailwind/**/*.js',
|
||||||
|
'./node_modules/flowbite/**/*.{js,ts}'
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('flowbite/plugin'),
|
||||||
|
require('@vueform/vueform/tailwind')
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
42
vueform.config.js
Normal file
42
vueform.config.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import en from '@vueform/vueform/locales/en'
|
||||||
|
import tailwind from '@vueform/vueform/themes/tailwind'
|
||||||
|
|
||||||
|
import { Validator } from '@vueform/vueform'
|
||||||
|
|
||||||
|
const phoneRule = class extends Validator {
|
||||||
|
get message() {
|
||||||
|
return 'The What is your primary phone number? filed requires a valid phone number'
|
||||||
|
}
|
||||||
|
|
||||||
|
check(value) {
|
||||||
|
return /^(07|01)(\d){8}$/.test(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
theme: tailwind,
|
||||||
|
locales: { en },
|
||||||
|
locale: 'en',
|
||||||
|
floatPlaceholders: false,
|
||||||
|
rules: {
|
||||||
|
phone: phoneRule,
|
||||||
|
},
|
||||||
|
endpoints: {
|
||||||
|
registration: {
|
||||||
|
url: `${process.env.BASE_URL}/registration`,
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
transaction: {
|
||||||
|
url: `${process.env.BASE_URL}/transaction`,
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
farmer: {
|
||||||
|
url: `${process.env.BASE_URL}/farmer`,
|
||||||
|
method: 'post'
|
||||||
|
},
|
||||||
|
distributor: {
|
||||||
|
url: `${process.env.BASE_URL}/distributor`,
|
||||||
|
method: 'post'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user