mirror of
https://github.com/Floriansylvain/snippets-manager-front.git
synced 2026-08-19 11:43:16 +02:00
feat: category creation
This commit is contained in:
@@ -1,31 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { useCategoriesStore } from '@/stores/categories'
|
||||
import { onMounted, ref, type Ref } from 'vue'
|
||||
import type { Category } from '@/composables/category'
|
||||
|
||||
interface Category {
|
||||
categories: {
|
||||
id: number
|
||||
name: string
|
||||
user_id: number
|
||||
}[]
|
||||
pagination: {
|
||||
skip: number
|
||||
take: number
|
||||
}
|
||||
links: {
|
||||
next: string
|
||||
prev: string
|
||||
}
|
||||
total: number
|
||||
}
|
||||
|
||||
const categoriesStore = useCategoriesStore()
|
||||
const fetchedCategories: Ref<Category | undefined> = ref()
|
||||
|
||||
onMounted(async () => {
|
||||
const categoriesPromise = await categoriesStore.getCategories()
|
||||
fetchedCategories.value = await categoriesPromise.json()
|
||||
})
|
||||
const props = defineProps<{
|
||||
fetchedCategories: Category | undefined
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,7 +12,7 @@ onMounted(async () => {
|
||||
{ title: 'Name', key: 'name', sortable: true },
|
||||
{ title: 'Actions', key: 'actions', align: 'end', sortable: false }
|
||||
]"
|
||||
:items="fetchedCategories?.categories"
|
||||
:items="props.fetchedCategories?.categories"
|
||||
>
|
||||
<template
|
||||
v-slot:[`item.actions`]="{
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { useCategoriesStore } from '@/stores/categories'
|
||||
import { ref, type Ref } from 'vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
categoryCreated: [id: number]
|
||||
}>()
|
||||
|
||||
const dialog: Ref<boolean> = ref(false)
|
||||
|
||||
const valid: Ref<boolean> = ref(false)
|
||||
const name: Ref<string> = ref('')
|
||||
const nameRules: Ref<Array<(v: string) => boolean | string>> = ref([
|
||||
(value) => {
|
||||
if (value.length > 0 && value.length <= 50) return true
|
||||
return `Name length should be below 50 characters. (currently: ${value.length})`
|
||||
}
|
||||
])
|
||||
|
||||
const categoriesStore = useCategoriesStore()
|
||||
|
||||
async function onSubmit(): Promise<void> {
|
||||
const createdCategoryPromise = await categoriesStore.postCategory(name.value)
|
||||
const createdCategory: { id: number } = await createdCategoryPromise.json()
|
||||
emit('categoryCreated', createdCategory.id)
|
||||
dialog.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VDialog v-model="dialog" max-width="500">
|
||||
<template v-slot:activator="{ props: activatorProps }">
|
||||
<VBtn
|
||||
prepend-icon="mdi-plus"
|
||||
text="Create Category"
|
||||
color="primary"
|
||||
variant="flat"
|
||||
v-bind="activatorProps"
|
||||
></VBtn>
|
||||
</template>
|
||||
<VCard prepend-icon="mdi-plus" title="Create Category">
|
||||
<VForm v-model="valid" @submit.prevent="onSubmit">
|
||||
<VCardText>
|
||||
<VText-field
|
||||
v-model="name"
|
||||
:rules="nameRules"
|
||||
label="Name*"
|
||||
variant="outlined"
|
||||
hide-details="auto"
|
||||
required
|
||||
></VText-field>
|
||||
</VCardText>
|
||||
<VDivider></VDivider>
|
||||
<VCardActions>
|
||||
<VSpacer></VSpacer>
|
||||
<VBtn color="primary" text="Close" variant="outlined" @click="dialog = false"></VBtn>
|
||||
<VBtn
|
||||
color="primary"
|
||||
text="Create"
|
||||
variant="flat"
|
||||
type="submit"
|
||||
:disabled="!valid"
|
||||
></VBtn>
|
||||
</VCardActions>
|
||||
</VForm>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface Category {
|
||||
categories: {
|
||||
id: number
|
||||
name: string
|
||||
user_id: number
|
||||
}[]
|
||||
pagination: {
|
||||
skip: number
|
||||
take: number
|
||||
}
|
||||
links: {
|
||||
next: string
|
||||
prev: string
|
||||
}
|
||||
total: number
|
||||
}
|
||||
+4
-6
@@ -13,10 +13,9 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
|
||||
const postLogin = async (credentials: LoginFields): Promise<Response> => {
|
||||
const loginPromise = await fetch(`${api.url}/session/login`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
...api.options,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(credentials),
|
||||
credentials: 'include'
|
||||
body: JSON.stringify(credentials)
|
||||
})
|
||||
cookie.setCookie('loggedIn', new Date(new Date().getTime() + 7200000).toString())
|
||||
return loginPromise
|
||||
@@ -24,9 +23,8 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
|
||||
const postLogout = async (): Promise<Response> => {
|
||||
return await fetch(`${api.url}/session/logout`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
...api.options,
|
||||
method: 'POST'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,17 @@ import { defineStore } from 'pinia'
|
||||
export const useCategoriesStore = defineStore('categories', () => {
|
||||
const api = useApi()
|
||||
|
||||
const getCategories = async () => {
|
||||
const getCategories = async (): Promise<Response> => {
|
||||
return await fetch(`${api.url}/category`, api.options)
|
||||
}
|
||||
|
||||
return { getCategories }
|
||||
const postCategory = async (name: string): Promise<Response> => {
|
||||
return await fetch(`${api.url}/category`, {
|
||||
...api.options,
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name })
|
||||
})
|
||||
}
|
||||
|
||||
return { getCategories, postCategory }
|
||||
})
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
<script setup lang="ts">
|
||||
import CategoriesTable from '@/components/CategoriesTable.vue'
|
||||
import CategoryCreate from '@/components/CategoryCreate.vue'
|
||||
import type { Category } from '@/composables/category'
|
||||
import { useCategoriesStore } from '@/stores/categories'
|
||||
import { onMounted, ref, type Ref } from 'vue'
|
||||
|
||||
const categoriesStore = useCategoriesStore()
|
||||
const fetchedCategories: Ref<Category | undefined> = ref()
|
||||
|
||||
async function updateCategories() {
|
||||
const categoriesPromise = await categoriesStore.getCategories()
|
||||
fetchedCategories.value = await categoriesPromise.json()
|
||||
}
|
||||
|
||||
onMounted(updateCategories)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="d-flex align-center justify-space-between">
|
||||
<h1 class="text-h3">Categories</h1>
|
||||
<VBtn prepend-icon="mdi-plus" variant="flat" color="primary">Create category</VBtn>
|
||||
<CategoryCreate @categoryCreated="updateCategories" />
|
||||
</header>
|
||||
<CategoriesTable />
|
||||
<CategoriesTable :fetched-categories="fetchedCategories" />
|
||||
</template>
|
||||
|
||||
@@ -39,7 +39,7 @@ async function onSubmit(): Promise<void> {
|
||||
<VTextField
|
||||
v-model="email"
|
||||
:rules="emailRules"
|
||||
label="E-mail"
|
||||
label="E-mail*"
|
||||
type="email"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
@@ -49,7 +49,7 @@ async function onSubmit(): Promise<void> {
|
||||
<div class="d-flex flex-column">
|
||||
<VTextField
|
||||
v-model="password"
|
||||
label="Password"
|
||||
label="Password*"
|
||||
type="password"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
|
||||
Reference in New Issue
Block a user