Template
feat : concept creation
This commit is contained in:
Vendored
+1
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"**/.nuxt": true,
|
||||
"**/.output": true,
|
||||
"**/node_modules": true
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+1
-1
Submodule netcode/events updated: 1473c5c132...24c39d23d6
Generated
+1192
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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",
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user