Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hugo castarede test #14

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions assets/css/main.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
:root {
--primary: rgba(255, 215, 122, 1);
--primary-light: rgba(255, 247, 228, 1);
--primary-dark: rgba(136, 71, 7, 1);
--secondary: rgba(0, 119, 98, 1);
--secondary-light: rgba(231, 254, 250, 1);
--secondary-dark: rgba(4, 78, 64, 1);
--accent: rgba(243, 189, 163, 1);
--accent-light: rgba(252, 239, 227, 1);
--white: rgba(255, 255, 255, 1);
--neutral: rgba(40, 56, 72, 1);
--neutral-light: rgba(239, 241, 241, 1);
--neutral-dark: rgba(13, 22, 28, 1);
--neutral-80: rgba(40, 56, 72, 0.8);
--neutral-60: rgba(40, 56, 72, 0.6);
--neutral-40: rgba(40, 56, 72, 0.4);
--neutral-20: rgba(40, 56, 72, 0.2);
--success: rgba(0, 119, 98, 1);
--success-light: rgba(225, 245, 238, 1);
--danger: rgba(191, 43, 13, 1);
--danger-light: rgba(245, 225, 225, 1);
--warning: rgba(148, 99, 0, 1);
--warning-light: rgba(254, 241, 215, 1);
--info: rgba(0, 41, 163, 1);
--info-light: rgba(229, 242, 255, 1);
--other-1: rgba(133, 10, 103, 1);
--other-1-light: rgba(247, 235, 244, 1);
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-Light.ttf') format('truetype');
font-weight: 300;
font-style: normal;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-LightItalic.ttf') format('truetype');
font-weight: 300;
font-style: italic;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-MediumItalic.ttf') format('truetype');
font-weight: 500;
font-style: italic;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-Bold.ttf') format('truetype');
font-weight: 700;
font-style: normal;
}

@font-face {
font-family: 'Poppins';
src: url('../fonts/Poppins-BoldItalic.ttf') format('truetype');
font-weight: 700;
font-style: italic;
}

html {
font-family: "Poppins", sans-serif;
}

Binary file added assets/fonts/Poppins-Bold.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-BoldItalic.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-Italic.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-Light.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-LightItalic.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-Medium.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-MediumItalic.ttf
Binary file not shown.
Binary file added assets/fonts/Poppins-Regular.ttf
Binary file not shown.
19 changes: 19 additions & 0 deletions components/CategoriesList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<div class="border-r border-neutral-light col-start-1 col-span-1 flex flex-col pt-5 px-2 h-full overflow-y-auto">
<div class="group flex items-center rounded px-2 py-3 hover:bg-primary hover:cursor-pointer" :key="-1"
@click="() => updateFilter(-1)">
<div class="w-[5px] h-full bg-primary rounded-sm mr-2 group-hover:hidden"></div>
<span>{{ categoriesStore.$state.nameForAll }}</span>
</div>
<div v-for="c in categoriesStore.categoriesList" :key="c.id" @click="() => updateFilter(c.id)"
class="group flex items-center rounded px-2 py-3 hover:bg-primary hover:cursor-pointer">
<div class="w-[5px] h-full rounded-sm mr-2 group-hover:hidden" :style="{ backgroundColor: c.color }" ></div>
<span>{{ c.name }}</span>
</div>
</div>
</template>

<script lang="ts" setup>
const categoriesStore = useCategoriesStore()
const { updateFilter } = useTasksStore()
</script>
65 changes: 65 additions & 0 deletions components/CreateModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<div v-if="isOpen" class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<form @submit.prevent=handleSubmit class="bg-white p-6 rounded-lg shadow-lg max-w-md min-w-[400px]">
<h1 class="text-lg font-bold mb-4">Créer une nouvelle tâche</h1>
<div class="flex flex-col w-full gap-y-6">
<div class="flex flex-col">
<label class="mb-1 text-gray-700 font-medium">Titre</label>
<input type="text" placeholder="titre" v-model="title"
class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" />
</div>
<div class="flex flex-col">
<label class="mb-1 text-gray-700 font-medium">Description</label>
<textarea placeholder="description" v-model="description"
class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" />
</div>

<div class="flex flex-col">
<label class="text-gray-700 font-medium mb-1">Choisir une / plusieurs catégories</label>
<div class="max-h-[200px] overflow-y-auto py-3 flex flex-col gap-y-2">
<div v-for="c in categoryStore.categoriesList" class="flex items-center gap-x-5 ">
<input type="checkbox" :id="c.id.toString()" :value="c.id" v-model="categories"
class="form-checkbox text-blue-500 hover:cursor-pointer">
<label :for="c.id.toString()" class="mr-2 hover:cursor-pointer">{{ c.name }}</label>
</div>
</div>
</div>


</div>
<div class="flex gap-x-10 justify-center mt-10">
<button class="mt-4 px-4 py-2 bg-primary rounded hover:opacity-90">Créer</button>
<button @click="emit('closeModal')"
class="mt-4 px-4 py-2 bg-danger text-white rounded hover:opacity-90">Fermer</button>
</div>

</form>
</div>
</template>

<script setup lang="ts">
defineProps<{ isOpen: boolean }>();

const emit = defineEmits<{
(e: "closeModal"): void;
}>();

const tasksStore = useTasksStore()
const categoryStore = useCategoriesStore()

const title = ref<string>("")
const description = ref<string>("")
const categories = ref<number[]>([])

const handleSubmit = async () => {
//todo validation (using zod for instance)
const content = {
title: title.value,
description: description.value,
categories: categories.value
}
await tasksStore.createTask(content)
emit("closeModal")
//todo catch errors
}
</script>
73 changes: 73 additions & 0 deletions components/EditModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<div v-if="isOpen" class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<form @submit.prevent=handleSubmit class="bg-white p-6 rounded-lg shadow-lg max-w-md min-w-[400px]">
<h1 class="text-lg font-bold mb-4">Modifier la tâche</h1>
<div class="flex flex-col w-full gap-y-6">
<div class="flex flex-col">
<label class="mb-1 text-gray-700 font-medium">Titre</label>
<input type="text" placeholder="titre" v-model="title"
class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" />
</div>
<div class="flex flex-col">
<label class="mb-1 text-gray-700 font-medium">Description</label>
<textarea placeholder="description" v-model="description"
class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" />
</div>

<div class="flex flex-col">
<label class="text-gray-700 font-medium mb-1">Choisir une / plusieurs catégories</label>
<div class="max-h-[200px] overflow-y-auto py-3 flex flex-col gap-y-2">
<div v-for="c in categoryStore.categoriesList" class="flex items-center gap-x-5 ">
<input type="checkbox" :id="c.id.toString()" :value="c.id" v-model="categories"
class="form-checkbox text-blue-500 hover:cursor-pointer">
<label :for="c.id.toString()" class="mr-2 hover:cursor-pointer">{{ c.name }}</label>
</div>
</div>
</div>


</div>
<div class="flex gap-x-10 justify-center mt-10">
<button class="mt-4 px-4 py-2 bg-primary rounded hover:opacity-90">Modifier</button>
<button @click="emit('closeModal')"
class="mt-4 px-4 py-2 bg-danger text-white rounded hover:opacity-90">Fermer</button>
</div>

</form>
</div>
</template>

<script setup lang="ts">
import type { Task } from "~/types/Task";

const props = defineProps<{ isOpen: boolean, task: Task }>();

const emit = defineEmits<{
(e: "closeModal"): void;
}>();

const tasksStore = useTasksStore()
const categoryStore = useCategoriesStore()

const title = ref<string>(props.task.title)
const description = ref<string>(props.task.description ?? "")
const categories = ref<number[]>(props.task.categories)

watchEffect(() => {
title.value = props.task.title;
description.value = props.task.description ?? "" ;
categories.value = props.task.categories;
});

const handleSubmit = async () => {
//todo validation (using zod for instance)
const content = {
title: title.value,
description: description.value,
categories: categories.value,
}
await tasksStore.updateTask(props.task.id, content)
emit("closeModal")
//todo catch errors
}
</script>
48 changes: 48 additions & 0 deletions components/TodoListElement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<EditModal :isOpen="isEditOpen" :task="task" @closeModal="isEditOpen = !isEditOpen" />
<div class="flex px-5 py-4 border border-neutral-l rounded-xl max-w-xl justify-between items-center">
<div class="flex gap-x-4 flex-grow">
<input class="hover:cursor-pointer w-4" type="checkbox" v-model="task.completed" />
<div class="flex flex-col">
<span :class="{ lineThrough: task.completed }">
{{ task.title }}
</span>
<span :class="{ lineThrough: task.completed }" class="text-sm text-neutral italic">
{{ task.description }}
</span>
<div class="flex w-full flex-wrap gap-x-4 mt-2">
<div v-for="c in getCategoriesFromId(task.categories)" class="flex items-center gap-x-1">
<div class="w-2 h-2 rounded-full ba" :style="{ backgroundColor: c.color }"></div>
<span class="text-sm text-neutral-60"> {{ c.name }}</span>

</div>
</div>
</div>
</div>
<div class="flex gap-x-4">
<button><font-awesome-icon icon="fa-solid fa-edit" @click="isEditOpen = !isEditOpen" /></button>
<button> <font-awesome-icon class="text-danger" icon="fa-solid fa-trash"
@click="() => deleteTask(task.id)" /></button>
</div>
</div>
</template>

<script lang="ts" setup>
import type { Task } from '~/types/Task';
import EditModal from './EditModal.vue';

defineProps<{
task: Task
}>()

const { getCategoriesFromId } = useCategoriesStore()
const { deleteTask } = useTasksStore()
const isEditOpen = ref(false)

</script>

<style>
.lineThrough {
text-decoration: line-through;
}
</style>
25 changes: 25 additions & 0 deletions components/TodosList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<div
class="border-r border-neutral-light col-start-2 col-span-1 px-5 py-4 grid grid-rows-[auto_1fr] grid-cols-1 w-full h-full overflow-y-auto">
<CreateModal :isOpen="isOpen" @closeModal="isOpen = !isOpen" />
<div class="row-start-1 row-span-1">
<div class="w-full flex items-center gap-x-5 mb-5">
<font-awesome-icon icon="fa-solid fa-list" />
<h1 class="text-3xl font-bold">{{ categoriesStore.currentCategory.name }}</h1>
</div>
<button class="px-10 py-4 bg-primary rounded-lg hover:opacity-90" @click="isOpen = !isOpen">+ Nouvelle
tâche</button>
</div>
<div class="mt-10 flex flex-col gap-y-4 row-start-2 row-span-2">
<TodoListElement v-for="t in taskStore.filteredTasksList" :task="t" />
</div>


</div>
</template>

<script lang="ts" setup>
const categoriesStore = useCategoriesStore()
const taskStore = useTasksStore()
const isOpen = ref(false)
</script>
15 changes: 15 additions & 0 deletions components/view/Todos.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<div class="w-full h-full grid grid-cols-[300px_1fr]">
<CategoriesList v-if="categoriesList.length" />
<TodosList v-if="tasksList.length" />
</div>
</template>

<script lang="ts" setup>
const { categoriesList, fetchCategories } = useCategoriesStore()
const { tasksList, fetchTasks } = useTasksStore()

await fetchTasks();
await fetchCategories();

</script>
12 changes: 12 additions & 0 deletions layouts/default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<div class="grid grid-cols-[70px_1fr] grid-rows-1 w-full h-screen">
<div class="col-start-1 bg-neutral-light row-span-1 col-span-1"></div>
<div class="col-start-2 bg-white row-span-1 col-span-1">
<slot />
</div>
</div>
</template>

<script lang="ts" setup>

</script>
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export default defineNuxtConfig({
compatibilityDate: '2024-04-03',
devtools: { enabled: true },
modules: ['@nuxtjs/tailwindcss', '@nuxt/eslint', '@pinia/nuxt'],
css: ['~/assets/css/main.scss'],
css: ['~/assets/css/main.scss', '@fortawesome/fontawesome-svg-core/styles.css'],
eslint: {
config: {
stylistic: true,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-regular-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/vue-fontawesome": "^3.0.8",
"@nuxtjs/tailwindcss": "^6.12.1",
"@pinia/nuxt": "^0.5.1",
Expand Down
6 changes: 1 addition & 5 deletions pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<template>
<div class="max-w-screen-md mx-auto p-5">
<div class="text-3xl font-bold mb-3">
Todo List
</div>
</div>
<ViewTodos />
</template>

<script setup lang="ts">
Expand Down
Loading