Skip to content

Commit

Permalink
Merge branch 'release/v0.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
MatiasOlivera committed Mar 1, 2020
2 parents 3fccf0b + f2a89b9 commit 647b4c8
Show file tree
Hide file tree
Showing 13 changed files with 512 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
},
"dependencies": {
"@vue/composition-api": "^0.4.0",
"validatorjs": "^3.18.1",
"vue": "^2.6.11",
"vue-router": "^3.1.5"
},
"devDependencies": {
"@types/validatorjs": "^3.15.0",
"@typescript-eslint/eslint-plugin": "^2.18.0",
"@typescript-eslint/parser": "^2.18.0",
"@vue/cli-plugin-eslint": "~4.2.0",
Expand Down
6 changes: 5 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>
<router-link to="/">Home</router-link> |
<router-link :to="{ name: 'Counter' }">Counter</router-link> |
<router-link :to="{ name: 'Posts' }">Posts</router-link> |
<router-link :to="{ name: 'Pagination' }">Pagination</router-link> |
<router-link :to="{ name: 'Validation' }">Validation</router-link> |
</div>
<router-view />
</div>
Expand Down
21 changes: 21 additions & 0 deletions src/api/posts-api.ts
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>;
14 changes: 14 additions & 0 deletions src/api/users-api.ts
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>;
68 changes: 68 additions & 0 deletions src/composables/use-pagination.ts
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;
}
33 changes: 33 additions & 0 deletions src/composables/use-promise.ts
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;
}
20 changes: 20 additions & 0 deletions src/composables/use-validator.ts
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
};
}
24 changes: 24 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Counter from "../views/Counter.vue";
import ValidationView from "../views/ValidationView.vue";
import NewPostsView from "../views/getting-data/NewPostsView.vue";
import NewPaginationView from "../views/pagination/NewPaginationView.vue";

Vue.use(VueRouter);

Expand All @@ -9,6 +13,26 @@ const routes = [
path: "/",
name: "Home",
component: Home
},
{
path: "/counter",
name: "Counter",
component: Counter
},
{
path: "/posts",
name: "Posts",
component: NewPostsView
},
{
path: "/pagination",
name: "Pagination",
component: NewPaginationView
},
{
path: "/validation",
name: "Validation",
component: ValidationView
}
];

Expand Down
35 changes: 35 additions & 0 deletions src/views/Counter.vue
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>
96 changes: 96 additions & 0 deletions src/views/ValidationView.vue
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>
Loading

0 comments on commit 647b4c8

Please sign in to comment.