Skip to content
This repository has been archived by the owner on Dec 18, 2023. It is now read-only.

Commit

Permalink
feat(frontend): finish delivery
Browse files Browse the repository at this point in the history
Signed-off-by: Fernando Fernández <[email protected]>
  • Loading branch information
ferferga authored Dec 13, 2023
1 parent 55ecb2a commit 7a24261
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 28 deletions.
2 changes: 1 addition & 1 deletion backend/traineerbook/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_PRIVATE_NETWORK = True
CSRF_TRUSTED_ORIGINS=['http://*', 'https://*']
CSRF_TRUSTED_ORIGINS=['https://localhost:80', 'https://*', 'http://*']

MIDDLEWARE = [
'traineerbook.middlewares.AddHeaderMiddleware',
Expand Down
11 changes: 4 additions & 7 deletions frontend/src/components/layout/CarritoHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@
v-slot="{ navigate }"
to="/cart"
custom>
<QAvatar
color="green"
class="mr-2 cursor-pointer"
@click="navigate">
<QBtn :disable="cart.cart.length === 0" @click="() => navigate">
<IMdiCart />
<QBadge
v-if="cart.length > 0"
v-if="cart.cart.length > 0"
color="red"
floating>
{{ cart.length }}
{{ cart.cart.length }}
</QBadge>
</QAvatar>
</QBtn>
</RouterLink>
</template>

Expand Down
32 changes: 29 additions & 3 deletions frontend/src/components/pages/clase/ComentariosActividad.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<template>
<QForm class="pa-10">
<QForm
v-if="$server.user"
class="pa-10">
<QInput
v-model="commentBody"
filled
type="textarea"
label="Deja un comentario" />
<div class="flex justify-end">
<QBtn
:loading="loading"
label="Enviar"
type="submit"
color="primary" />
color="primary"
@click.prevent="submitComment" />
</div>
</QForm>

Expand All @@ -36,8 +40,30 @@

<script setup lang="ts">
import { Comment } from '@/api';
import { useServer } from '@/composables';
import { ref } from 'vue';
const props = defineProps<{ comments: Comment[] }>();
const props = defineProps<{ comments: Comment[], id: number }>();
const emit = defineEmits<{
'update': [];
}>();
const server = useServer();
const commentBody = ref('');
const loading = ref(false);
/**
* Send comment
*/
async function submitComment(): Promise<void> {
try {
loading.value = true;
await server.api.comment.commentCreateCreate({
activity: props.id,
content: commentBody.value
});
emit('update');
} catch {
loading.value = true;
}
}
</script>
19 changes: 15 additions & 4 deletions frontend/src/components/pages/clase/TablaActividad.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
bordered
:rows="rows"
:columns="columns"
row-key="name"
row-key="key"
hide-bottom
virtual-scroll
selection="multiple" />
Expand All @@ -18,7 +18,7 @@
class="ma-3"
:label="selected.length > 0 ? `Añadir al carrito (${selected.length} elementos)` : 'Añadir al carrito'"
color="purple"
@click="cart.concat(selected)">
@click="addToCart">
<IMdiCart />
</QBtn>
<RouterLink
Expand All @@ -31,7 +31,7 @@
text-color="black"
:label="selected.length > 0 ? `Comprar ya (${selected.length} elementos)` : 'Comprar ya'"
@click="() => {
cart.concat(selected)
addToCart()
navigate()
}" />
</RouterLink>
Expand All @@ -46,7 +46,7 @@ import { computed, ref } from 'vue';
const props = defineProps<{ products: Product[] }>();
const selected = ref([]);
const selected = ref<typeof rows.value>([]);
const cart = useCart();
interface Column {
Expand Down Expand Up @@ -85,6 +85,7 @@ const rows = computed(() => {
const stringHoraFin = `${horaFin}:${minutosFin}`;
return {
key: product.id,
'dia_start': stringInicio,
'dia_fin': stringFin,
'hora_start': stringHoraInicio,
Expand All @@ -94,4 +95,14 @@ const rows = computed(() => {
});
});
function addToCart() {
const cartsId = cart.value.cart.map((item) => item.id);
const productsToAdd = selected.value.map((item) =>
props.products.find((product) => product.id === item.key))
.filter((i) => i !== undefined)
.filter((i) => !cartsId.includes(i?.id));
cart.value.cart = [...cart.value.cart, ...productsToAdd as Product[]];
}
</script>
16 changes: 12 additions & 4 deletions frontend/src/composables/use-cart.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { Product } from '@/api';
import { Ref, ref } from 'vue';
import { useStorage } from '@vueuse/core';

export const cart = useStorage(
'cart',
{
cart: [] as Product[],
quantityMap: new Map<number, number>()
},
localStorage
);

export const cart = ref<Product[]>([]);
/**
*
* Retuns cart store
*/
export function useCart(): Ref<Product[]> {
export function useCart(): typeof cart {
return cart;
}
36 changes: 36 additions & 0 deletions frontend/src/pages/cart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<h3 style="text-align: center">
CARRITO
</h3>
<QList>
<QItem
v-for="item in cart.cart"
:key="item.id">
<QItemSection>
<QImg
v-if="getActivityFromProduct(item.id)?.image.data"
:src="getActivityFromProduct(item.id)?.image.data" />
<QItemLabel v-if="getActivityFromProduct(item.id)?.name">{{ getActivityFromProduct(item.id)?.name }}</QItemLabel>
</QItemSection>
<QItemSection side>
<QItemLabel>{{ item.price }}€</QItemLabel>
</QItemSection>
</QItem>
</QList>
</template>
<script setup lang="ts">
import { Activity } from '@/api';
import { activities } from '@/composables/use-activities';
import { useCart } from '@/composables/use-cart';
const cart = useCart();
function getActivityFromProduct(id: number | undefined): Activity | undefined {
return activities.value.find(i => i.id === id);
}
function updateQuantity(productId: number, quantity: number) {
cart.value.quantityMap.set(productId, quantity);
}
</script>
7 changes: 5 additions & 2 deletions frontend/src/pages/clase/[id].vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
v-if="activity"
v-if="activity && activity.id"
style="margin-top: 5%;">
<div class="row">
<div class="col-6">
Expand All @@ -21,7 +21,10 @@
<h3 style="margin-left: 20px;">
Comentarios
</h3>
<ComentariosActividad :comments="comments" />
<ComentariosActividad
:id="activity.id"
:comments="comments"
@update="fetchData" />
</div>
<h1 v-else>
No se ha encontrado la actividad
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@

<script setup lang="ts">
import { activities } from '@/composables/use-activities';
console.log(activities.value);
</script>

<style scoped>
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/pages/register.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
v-model="password"
class="form-field"
filled
type="password"
label="Contraseña"
lazy-rules
:disable="loading"
Expand Down Expand Up @@ -101,8 +102,6 @@ async function submitForm(): Promise<void> {
await server.signUpUser(username.value, password.value, email.value, rememberMe.value);
console.log(server.user);
if (server.user) {
await router.replace('/');
}
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/plugins/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { mergeExcludingUnknown } from '@/utils/data-manipulation';
import { useStorage } from '@vueuse/core';
import axios, { AxiosError } from 'axios';
import { Notify } from 'quasar';
import { watch } from 'vue';
import { watchEffect } from 'vue';

interface AuthState {
token?: string;
Expand All @@ -32,7 +32,8 @@ class ServerPlugin {
private _defaultState: AuthState = {
token: undefined,
user: undefined,
rememberMe: false }; private _state = useStorage(
rememberMe: false };
private _state = useStorage(
'auth',
structuredClone(this._defaultState),
localStorage,
Expand Down Expand Up @@ -123,7 +124,7 @@ class ServerPlugin {
/**
* Configure app's axios instance to perform requests to the server and clear itself when necessary.
*/
watch(() => this._state.value.token, async () => {
watchEffect(async () => {
if (this._state.value.token) {
try {
this._axios.defaults.headers.common.Authorization = `Token ${this._state.value.token}`;
Expand Down
1 change: 1 addition & 0 deletions frontend/types/global/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ declare module 'vue' {
QImg: typeof import('quasar')['QImg']
QInput: typeof import('quasar')['QInput']
QItem: typeof import('quasar')['QItem']
QItemLabel: typeof import('quasar')['QItemLabel']
QItemSection: typeof import('quasar')['QItemSection']
QLayout: typeof import('quasar')['QLayout']
QList: typeof import('quasar')['QList']
Expand Down
1 change: 1 addition & 0 deletions frontend/types/global/routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import type {
declare module 'vue-router/auto/routes' {
export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/cart': RouteRecordInfo<'/cart', '/cart', Record<never, never>, Record<never, never>>,
'/clase/[id]': RouteRecordInfo<'/clase/[id]', '/clase/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/issues': RouteRecordInfo<'/issues', '/issues', Record<never, never>, Record<never, never>>,
'/issues/new': RouteRecordInfo<'/issues/new', '/issues/new', Record<never, never>, Record<never, never>>,
Expand Down

0 comments on commit 7a24261

Please sign in to comment.