-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
512 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export function getPosts(params: Params): Promise<Posts> { | ||
return fetch( | ||
`https://jsonplaceholder.typicode.com/posts?_start=${params.start}&_limit=${params.limit}` | ||
) | ||
.then(response => response.json()) | ||
.catch(error => { | ||
throw error; | ||
}); | ||
} | ||
|
||
interface Params { | ||
start: number; | ||
limit: number; | ||
} | ||
|
||
interface Post { | ||
id: number; | ||
title: string; | ||
} | ||
|
||
export type Posts = Array<Post>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export function getUsers(): Promise<Users> { | ||
return fetch("https://jsonplaceholder.typicode.com/users?_start=0&_limit=5") | ||
.then(response => response.json()) | ||
.catch(error => { | ||
throw error; | ||
}); | ||
} | ||
|
||
interface User { | ||
id: number; | ||
name: string; | ||
} | ||
|
||
export type Users = Array<User>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { ref, computed } from "@vue/composition-api"; | ||
|
||
function minMax(value: number, min: number, max: number): number { | ||
if (value < min) return min; | ||
if (value > max) return max; | ||
return value; | ||
} | ||
|
||
export function usePagination(options: Options) { | ||
// State | ||
const _currentPage = ref<number>(options.startPage ?? 1); | ||
const perPage = ref<number>(options.perPage ?? 10); | ||
const total = ref<number>(options.total ?? 0); | ||
|
||
// Computed | ||
const currentPage = computed<number>(() => _currentPage.value); | ||
|
||
const lastPage = computed<number>(() => | ||
Math.ceil(total.value / perPage.value) | ||
); | ||
|
||
const offset = computed<number>( | ||
() => (_currentPage.value - 1) * perPage.value | ||
); | ||
|
||
// Functions | ||
function setCurrentPage(page: number): void { | ||
_currentPage.value = minMax(page, 1, lastPage.value); | ||
} | ||
|
||
function prev(): void { | ||
setCurrentPage(_currentPage.value - 1); | ||
} | ||
|
||
function next(): void { | ||
setCurrentPage(_currentPage.value + 1); | ||
} | ||
|
||
function first(): void { | ||
setCurrentPage(1); | ||
} | ||
|
||
function last(): void { | ||
setCurrentPage(lastPage.value); | ||
} | ||
|
||
return { | ||
// State | ||
currentPage, | ||
perPage, | ||
|
||
// Computed | ||
lastPage, | ||
offset, | ||
|
||
// Functions | ||
prev, | ||
next, | ||
first, | ||
last | ||
}; | ||
} | ||
|
||
interface Options { | ||
startPage?: number; | ||
perPage?: number; | ||
total: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { reactive } from "@vue/composition-api"; | ||
|
||
export function usePromise<Data>(callback: () => Promise<Data>) { | ||
const state = (reactive({ | ||
loading: false, | ||
error: null, | ||
data: null | ||
}) as unknown) as State<Data>; | ||
|
||
async function load() { | ||
state.error = null; | ||
state.loading = true; | ||
|
||
try { | ||
state.data = await callback(); | ||
} catch (error) { | ||
state.error = error; | ||
} finally { | ||
state.loading = false; | ||
} | ||
} | ||
|
||
return { | ||
state, | ||
load | ||
}; | ||
} | ||
|
||
interface State<Data> { | ||
loading: boolean; | ||
error: string | null; | ||
data: Data | null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { ref, watch, Ref } from "@vue/composition-api"; | ||
import Validator from "validatorjs"; | ||
|
||
export function useValidator<Data>(data: Ref<Data>, rules: Validator.Rules) { | ||
const passes = ref<boolean>(false); | ||
const errors = ref<Validator.ValidationErrors>({}); | ||
|
||
function validate(): void { | ||
const validator = new Validator(data.value, rules); | ||
passes.value = validator.passes() as boolean; | ||
errors.value = validator.errors.errors; | ||
} | ||
|
||
watch([data], () => validate(), { deep: true, lazy: true }); | ||
|
||
return { | ||
passes, | ||
errors | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<template> | ||
<div> | ||
<button @click="increment">Increment</button> | ||
<button @click="reset">Reset</button> | ||
{{ count }} | ||
</div> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, ref } from "@vue/composition-api"; | ||
const Counter = defineComponent({ | ||
setup() { | ||
const count = ref<number>(0); | ||
function increment(): void { | ||
count.value++; | ||
} | ||
function reset(): void { | ||
count.value = 0; | ||
} | ||
return { | ||
count, | ||
increment, | ||
reset | ||
}; | ||
} | ||
}); | ||
export default Counter; | ||
</script> | ||
|
||
<style scoped></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<template> | ||
<form @submit.prevent="onSubmit"> | ||
<fieldset> | ||
<label for="firstName">First name</label> | ||
<input | ||
v-model="person.firstName" | ||
type="text" | ||
name="firstName" | ||
id="firstName" | ||
/> | ||
<p v-if="errors.firstName">{{ errors.firstName[0] }}</p> | ||
</fieldset> | ||
|
||
<fieldset> | ||
<label for="lastName">Last name</label> | ||
<input | ||
v-model="person.lastName" | ||
type="text" | ||
name="lastName" | ||
id="lastName" | ||
/> | ||
<p v-if="errors.lastName">{{ errors.lastName[0] }}</p> | ||
</fieldset> | ||
|
||
<fieldset> | ||
<label for="email">Email</label> | ||
<input v-model="person.email" type="email" name="email" id="email" /> | ||
<p v-if="errors.email">{{ errors.email[0] }}</p> | ||
</fieldset> | ||
|
||
<button type="submit" :disabled="!passes">Save</button> | ||
</form> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, ref } from "@vue/composition-api"; | ||
import { useValidator } from "../composables/use-validator"; | ||
const personRules: PersonRules = { | ||
firstName: ["required", "alpha", "between:3,15"], | ||
lastName: ["required", "alpha", "between:3,15"], | ||
email: ["required", "email"] | ||
}; | ||
const ValidationView = defineComponent({ | ||
name: "ValidationView", | ||
setup() { | ||
const person = ref<Person>({ | ||
firstName: "", | ||
lastName: "", | ||
email: "" | ||
}); | ||
const { passes, errors } = useValidator(person, personRules); | ||
function onSubmit(): void { | ||
console.log("submit"); | ||
} | ||
return { person, passes, errors, onSubmit }; | ||
} | ||
}); | ||
interface Person { | ||
firstName: string; | ||
lastName: string; | ||
email: string; | ||
} | ||
interface PersonRules extends Validator.Rules { | ||
firstName: string[]; | ||
lastName: string[]; | ||
email: string[]; | ||
} | ||
export default ValidationView; | ||
</script> | ||
|
||
<style scoped> | ||
fieldset { | ||
display: flex; | ||
flex-direction: column; | ||
border: none; | ||
} | ||
button { | ||
margin-left: 1em; | ||
} | ||
p { | ||
color: tomato; | ||
margin-block-start: 0.5em; | ||
margin-block-end: 0; | ||
} | ||
</style> |
Oops, something went wrong.