feat : concept creation

This commit is contained in:
2025-01-13 22:33:55 +01:00
parent 8223ca5166
commit 452d76ca4b
8 changed files with 1279 additions and 54 deletions
+1
View File
@@ -1,6 +1,7 @@
{
"files.exclude": {
"**/.nuxt": true,
"**/.output": true,
"**/node_modules": true
}
}
+6 -2
View File
@@ -1,11 +1,15 @@
<script setup lang="ts">
import { useUserStore } from "~/store/user.store";
import { useLobbyStore } from "./store/lobby.store";
import { useConceptStore } from "./store/concepts.store";
const userStore = useUserStore();
const lobbyStore = useLobbyStore();
const conceptStore = useConceptStore()
void userStore.whoami();
void conceptStore.fetchConceptTypes();
void lobbyStore.fetchGames();
userStore.whoami();
lobbyStore.fetchGames();
onBeforeMount(() => {
lobbyStore.subscribe();
});
+28 -25
View File
@@ -1,10 +1,13 @@
import typescriptEslintEslintPlugin from '@typescript-eslint/eslint-plugin';
import globals from 'globals';
import tsParser from '@typescript-eslint/parser';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import js from '@eslint/js';
import { FlatCompat } from '@eslint/eslintrc';
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin";
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -16,15 +19,15 @@ const compat = new FlatCompat({
export default [
{
ignores: ['**/.eslintrc.js'],
ignores: ["**/.eslintrc.js"],
},
...compat.extends(
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:prettier/recommended',
"plugin:@typescript-eslint/recommended-type-checked",
"plugin:prettier/recommended"
),
{
plugins: {
'@typescript-eslint': typescriptEslintEslintPlugin,
"@typescript-eslint": typescriptEslintEslintPlugin,
},
languageOptions: {
@@ -35,27 +38,27 @@ export default [
parser: tsParser,
ecmaVersion: 5,
sourceType: 'module',
sourceType: "module",
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: '/home/legonzaur/Documents/code/concept/back',
project: "tsconfig.json",
tsconfigRootDir: __dirname,
},
},
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/no-unused-vars': [
'warn',
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"require-await": "off",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
+1192
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -18,5 +18,14 @@
"vue": "latest",
"vue-multiselect": "^3.1.0",
"vue-router": "latest"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.20.0",
"@typescript-eslint/parser": "^8.20.0",
"@typescript-eslint/typescript-estree": "^8.20.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.1",
"typescript-eslint": "^8.20.0"
}
}
+11 -14
View File
@@ -5,7 +5,10 @@ import { useConceptStore } from "~/store/concepts.store";
const newConcept = ref("");
const conceptStore = useConceptStore();
await conceptStore.fetchConceptList();
await Promise.all([
conceptStore.fetchConceptList()
])
const loading = ref(false);
const conceptInput = ref<HTMLInputElement | null>(null);
@@ -49,25 +52,18 @@ onUnmounted(() => {
<span>Delete</span>
<span>Type</span>
</div>
<div
class="concept"
v-for="concept in conceptStore.concepts"
:key="concept.id"
>
<div class="concept" v-for="concept in conceptStore.concepts" :key="concept.id">
<span>{{ concept.value }}</span>
<input type="checkbox" checked="true" disabled="true" />
<input type="button" value="Delete" @click="deleteConcept(concept.id)" />
<Multiselect :options="[]"></Multiselect>
<Multiselect :options="Object.values(conceptStore.conceptTypes)" track-by="id"
deselect-label="Can't remove this value" :allow-empty="false" label="value" v-model="concept.type">
</Multiselect>
</div>
<div class="new-concept">
<span>
<input
ref="conceptInput"
type="text"
:disabled="loading"
@keypress.enter="createConcept"
v-model="newConcept"
/>
<input ref="conceptInput" type="text" :disabled="loading" @keypress.enter="createConcept"
v-model="newConcept" />
<button :disabled="loading" @click="createConcept">Submit</button>
</span>
</div>
@@ -84,6 +80,7 @@ div.concept {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
div.header {
display: grid;
grid-template-columns: repeat(4, 1fr);
+31 -12
View File
@@ -1,34 +1,54 @@
import { defineStore } from "pinia";
import { subscribe } from "~/netcode";
import type { ConceptResponseDTO } from "~/netcode/events/dto/conceptresponse.dto";
import type {
ConceptResponseDTO,
ConceptTypeResponseDTO,
} from "~/netcode/events/dto/conceptresponse.dto";
import type { ConceptEvent } from "~/netcode/events/events";
import { handlers } from "~/netcode/handlers/concept.handler";
export const useConceptStore = defineStore("concept", {
state: () => ({
concepts: {} as Record<string, ConceptResponseDTO>,
eventSource: null as null | EventSource,
conceptTypes: {} as Record<string, ConceptTypeResponseDTO>,
}),
actions: {
async subscribe() {
subscribe() {
this.eventSource = subscribe(`/concepts/subscribe`);
this.eventSource.addEventListener("message", async (message) => {
const data = JSON.parse(message.data);
const type = data.type as string;
this.eventSource.addEventListener("message", (message) => {
const data = JSON.parse(message.data) as ConceptEvent;
const type = data.type;
if (type in handlers) {
handlers[type as keyof typeof handlers](data);
}
});
},
async close() {
close() {
this.eventSource?.close();
},
async fetchConceptTypes() {
const config = useRuntimeConfig();
const data = await useFetch<ConceptTypeResponseDTO[]>(
config.public.endpoint + `/concepts/types`,
{
credentials: "include",
},
);
if (data.data.value && !data.error.value) {
for (const conceptType of data.data.value) {
this.conceptTypes[conceptType.id] = conceptType;
}
}
return this.conceptTypes;
},
async fetchConceptList() {
const config = useRuntimeConfig();
const data = await useFetch<ConceptResponseDTO[]>(
config.public.endpoint + `/concepts/all`,
{
credentials: "include",
}
},
);
if (data.data.value && !data.error.value) {
for (const concept of data.data.value) {
@@ -44,7 +64,7 @@ export const useConceptStore = defineStore("concept", {
{
credentials: "include",
method: "PUT",
}
},
);
// word.enabled = true;
// return data;
@@ -56,12 +76,11 @@ export const useConceptStore = defineStore("concept", {
{
credentials: "include",
method: "PUT",
}
},
);
// word.enabled = false;
// return data;
},
async createConcept(value: string) {
const config = useRuntimeConfig();
const data = await $fetch<ConceptResponseDTO>(
@@ -70,7 +89,7 @@ export const useConceptStore = defineStore("concept", {
credentials: "include",
body: { value },
method: "POST",
}
},
);
},
async deleteConcept(id: number) {
@@ -80,7 +99,7 @@ export const useConceptStore = defineStore("concept", {
{
credentials: "include",
method: "DELETE",
}
},
);
},
},