Cleaner separation in components

This commit is contained in:
Lucas Verney 2018-03-11 12:45:52 +01:00
parent 55751467f8
commit da844e0a08
8 changed files with 290 additions and 226 deletions

View File

@ -0,0 +1,160 @@
<template>
<v-flex xs12>
<h2>{{ $t('new.add_manually') }}</h2>
<v-form v-model="isValidAdd">
<v-text-field
:label="$t('new.title')"
v-model="title"
required
:rules="[v => !!v || $t('new.title_is_required')]"
></v-text-field>
<v-text-field
:label="$t('new.picture_url')"
v-model="picture_url"
:rules="urlRules"
></v-text-field>
<v-text-field
:label="$t('new.short_description')"
v-model="short_description"
textarea
></v-text-field>
<v-layout row wrap>
<v-flex xs12 md5>
<v-text-field
:label="$t('new.preparation_time')"
v-model="preparation_time"
type="number"
:suffix="$t('new.mins')"
></v-text-field>
</v-flex>
<v-flex xs12 md5 offset-md2>
<v-text-field
:label="$t('new.cooking_time')"
v-model="cooking_time"
type="number"
:suffix="$t('new.mins')"
></v-text-field>
</v-flex>
</v-layout>
<v-text-field
:label="$t('new.nb_persons')"
v-model="nb_person"
></v-text-field>
<v-layout row>
<v-flex xs12 class="text-xs-left">
<h3>{{ $t('new.ingredients') }}</h3>
<v-list v-if="ingredients.length" class="transparent">
<v-list-tile v-for="ingredient in ingredients" :key="ingredient">
<v-list-tile-action>
<v-btn flat icon color="red" v-on:click="() => removeIngredient(ingredient)">
<v-icon>delete</v-icon>
</v-btn>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ ingredient }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<p class="ml-5 my-3" v-else>{{ $t('new.none') }}</p>
<v-text-field
:label="$t('new.add_ingredient')"
v-model="new_ingredient"
@keyup.enter.native="addIngredient"
></v-text-field>
</v-flex>
</v-layout>
<v-text-field
:label="$t('new.instructions')"
v-model="instructions"
:rules="[v => !!v || $t('new.instructions_are_required')]"
textarea
required
></v-text-field>
<v-btn
@click="submitAdd"
:disabled="!isValidAdd || isImporting"
>
{{ $t('new.add') }}
</v-btn>
</v-form>
</v-flex>
</template>
<script>
import * as api from '@/api';
import * as rules from '@/rules';
export default {
props: {
value: Boolean,
},
computed: {
isImporting: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
},
},
},
data() {
return {
url: null,
isValidAdd: false,
title: null,
picture_url: null,
short_description: null,
nb_person: null,
preparation_time: null,
cooking_time: null,
new_ingredient: null,
ingredients: [],
instructions: null,
urlRules: rules.url,
};
},
methods: {
addIngredient() {
this.ingredients.push(this.new_ingredient);
this.new_ingredient = null;
},
removeIngredient(ingredient) {
const index = this.ingredients.indexOf(ingredient);
if (index !== -1) {
this.ingredients.splice(index, 1);
}
},
submitAdd() {
this.isImporting = true;
api.postRecipeManually({
title: this.title,
picture_url: this.picture_url,
short_description: this.short_description,
preparation_time: this.preparation_time,
cooking_time: this.cooking_time,
nb_person: this.nb_person,
ingredients: this.ingredients,
instructions: this.instructions,
})
.then(response => this.$router.push({
name: 'Recipe',
params: {
recipeId: response.recipes[0].id,
},
}))
.catch((error) => {
this.isImporting = false;
this.error = error;
});
},
},
};
</script>
<style scoped>
.transparent {
background: transparent;
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<v-flex xs12>
<ErrorDialog v-model="error" :description="$t('error.unable_import_recipe')" />
<h2>{{ $t('new.import_from_url') }}</h2>
<v-form v-model="isValidImport">
<v-text-field
label="URL"
v-model="url"
required
:rules="requiredUrlRules"
></v-text-field>
<v-btn
@click="submitImport"
:disabled="!isValidImport || isImporting"
>
{{ $t('new.import') }}
</v-btn>
</v-form>
</v-flex>
</template>
<script>
import * as api from '@/api';
import * as rules from '@/rules';
import ErrorDialog from '@/components/ErrorDialog';
export default {
props: {
value: Boolean,
},
computed: {
isImporting: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
},
},
},
components: {
ErrorDialog,
},
data() {
return {
error: null,
url: null,
isValidImport: false,
requiredUrlRules: Array.concat(
[],
[v => !!v || this.$t('new.url_is_required')],
rules.url,
),
};
},
methods: {
submitImport() {
this.isImporting = true;
api.postRecipeByUrl({ url: this.url })
.then(response => this.$router.push({
name: 'Recipe',
params: {
recipeId: response.recipes[0].id,
},
}))
.catch((error) => {
this.isImporting = false;
this.error = error;
});
},
},
};
</script>

View File

@ -1,223 +0,0 @@
<template>
<v-container text-xs-center v-if="isImporting">
<v-layout row wrap>
<Loader></Loader>
<v-flex xs12>
<p>{{ $t('new.importing') }}</p>
</v-flex>
</v-layout>
</v-container>
<v-container text-xs-center v-else class="panel">
<v-layout row wrap>
<ErrorDialog v-model="error" :description="$t('error.unable_import_recipe')" />
<v-flex xs12>
<h2>{{ $t('new.import_from_url') }}</h2>
<v-form v-model="isValidImport">
<v-text-field
label="URL"
v-model="url"
required
:rules="requiredUrlRules"
></v-text-field>
<v-btn
@click="submitImport"
:disabled="!isValidImport || isImporting"
>
{{ $t('new.import') }}
</v-btn>
</v-form>
</v-flex>
</v-layout>
<v-layout row wrap mt-5>
<v-flex xs12>
<h2>{{ $t('new.add_manually') }}</h2>
<v-form v-model="isValidAdd">
<v-text-field
:label="$t('new.title')"
v-model="title"
required
:rules="[v => !!v || $t('new.title_is_required')]"
></v-text-field>
<v-text-field
:label="$t('new.picture_url')"
v-model="picture_url"
:rules="urlRules"
></v-text-field>
<v-text-field
:label="$t('new.short_description')"
v-model="short_description"
textarea
></v-text-field>
<v-layout row wrap>
<v-flex xs12 md5>
<v-text-field
:label="$t('new.preparation_time')"
v-model="preparation_time"
type="number"
:suffix="$t('new.mins')"
></v-text-field>
</v-flex>
<v-flex xs12 md5 offset-md2>
<v-text-field
:label="$t('new.cooking_time')"
v-model="cooking_time"
type="number"
:suffix="$t('new.mins')"
></v-text-field>
</v-flex>
</v-layout>
<v-text-field
:label="$t('new.nb_persons')"
v-model="nb_person"
></v-text-field>
<v-layout row>
<v-flex xs12 class="text-xs-left">
<h3>{{ $t('new.ingredients') }}</h3>
<v-list v-if="ingredients.length" class="transparent">
<v-list-tile v-for="ingredient in ingredients" :key="ingredient">
<v-list-tile-action>
<v-btn flat icon color="red" v-on:click="() => removeIngredient(ingredient)">
<v-icon>delete</v-icon>
</v-btn>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ ingredient }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<p class="ml-5 my-3" v-else>{{ $t('new.none') }}</p>
<v-text-field
:label="$t('new.add_ingredient')"
v-model="new_ingredient"
@keyup.enter.native="addIngredient"
></v-text-field>
</v-flex>
</v-layout>
<v-text-field
:label="$t('new.instructions')"
v-model="instructions"
:rules="[v => !!v || $t('new.instructions_are_required')]"
textarea
required
></v-text-field>
<v-btn
@click="submitAdd"
:disabled="!isValidAdd || isImporting"
>
{{ $t('new.add') }}
</v-btn>
</v-form>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import * as api from '@/api';
import ErrorDialog from '@/components/ErrorDialog';
import Loader from '@/components/Loader';
export default {
components: {
ErrorDialog,
Loader,
},
data() {
const urlRules = [
(v) => {
if (!v) {
return true;
}
try {
new URL(v); // eslint-disable-line no-new
return true;
} catch (e) {
return this.$t('new.url_must_be_valid');
}
},
];
return {
error: null,
url: null,
isValidImport: false,
isImporting: false,
isValidAdd: false,
title: null,
picture_url: null,
short_description: null,
nb_person: null,
preparation_time: null,
cooking_time: null,
new_ingredient: null,
ingredients: [],
instructions: null,
requiredUrlRules: Array.concat(
[],
[v => !!v || this.$t('new.url_is_required')],
urlRules,
),
urlRules,
};
},
methods: {
addIngredient() {
this.ingredients.push(this.new_ingredient);
this.new_ingredient = null;
},
removeIngredient(ingredient) {
const index = this.ingredients.indexOf(ingredient);
if (index !== -1) {
this.ingredients.splice(index, 1);
}
},
submitImport() {
this.isImporting = true;
api.postRecipeByUrl({ url: this.url })
.then(response => this.$router.push({
name: 'Recipe',
params: {
recipeId: response.recipes[0].id,
},
}))
.catch((error) => {
this.isImporting = false;
this.error = error;
});
},
submitAdd() {
this.isImporting = true;
api.postRecipeManually({
title: this.title,
picture_url: this.picture_url,
short_description: this.short_description,
preparation_time: this.preparation_time,
cooking_time: this.cooking_time,
nb_person: this.nb_person,
ingredients: this.ingredients,
instructions: this.instructions,
})
.then(response => this.$router.push({
name: 'Recipe',
params: {
recipeId: response.recipes[0].id,
},
}))
.catch((error) => {
this.isImporting = false;
this.error = error;
});
},
},
};
</script>
<style scoped>
.transparent {
background: transparent;
}
</style>

View File

@ -1,8 +1,8 @@
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/components/Home';
import New from '@/components/New';
import Recipe from '@/components/Recipe';
import Home from '@/views/Home';
import New from '@/views/New';
import Recipe from '@/views/Recipe';
Vue.use(Router);

13
cuizin/js_src/rules.js Normal file
View File

@ -0,0 +1,13 @@
export const url = [
(v) => {
if (!v) {
return true;
}
try {
new URL(v); // eslint-disable-line no-new
return true;
} catch (e) {
return this.$t('new.url_must_be_valid');
}
},
];

View File

@ -0,0 +1,39 @@
<template>
<v-container text-xs-center v-if="isImporting">
<v-layout row wrap>
<Loader></Loader>
<v-flex xs12>
<p>{{ $t('new.importing') }}</p>
</v-flex>
</v-layout>
</v-container>
<v-container text-xs-center v-else class="panel">
<v-layout row wrap>
<ImportForm v-model="isImporting"></ImportForm>
</v-layout>
<v-layout row wrap mt-5>
<EditForm v-model="isImporting"></EditForm>
</v-layout>
</v-container>
</template>
<script>
import EditForm from '@/components/EditForm';
import ImportForm from '@/components/ImportForm';
import Loader from '@/components/Loader';
export default {
components: {
EditForm,
ImportForm,
Loader,
},
data() {
return {
isImporting: false,
};
},
};
</script>