Template
feat : concept creation
This commit is contained in:
Vendored
+1
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"files.exclude": {
|
"files.exclude": {
|
||||||
"**/.nuxt": true,
|
"**/.nuxt": true,
|
||||||
|
"**/.output": true,
|
||||||
"**/node_modules": true
|
"**/node_modules": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useUserStore } from "~/store/user.store";
|
import { useUserStore } from "~/store/user.store";
|
||||||
import { useLobbyStore } from "./store/lobby.store";
|
import { useLobbyStore } from "./store/lobby.store";
|
||||||
|
import { useConceptStore } from "./store/concepts.store";
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const lobbyStore = useLobbyStore();
|
const lobbyStore = useLobbyStore();
|
||||||
|
const conceptStore = useConceptStore()
|
||||||
|
|
||||||
|
void userStore.whoami();
|
||||||
|
void conceptStore.fetchConceptTypes();
|
||||||
|
void lobbyStore.fetchGames();
|
||||||
|
|
||||||
userStore.whoami();
|
|
||||||
lobbyStore.fetchGames();
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
lobbyStore.subscribe();
|
lobbyStore.subscribe();
|
||||||
});
|
});
|
||||||
|
|||||||
+28
-25
@@ -1,10 +1,13 @@
|
|||||||
import typescriptEslintEslintPlugin from '@typescript-eslint/eslint-plugin';
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
import globals from 'globals';
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import tsParser from '@typescript-eslint/parser';
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import path from 'node:path';
|
import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin";
|
||||||
import { fileURLToPath } from 'node:url';
|
import globals from "globals";
|
||||||
import js from '@eslint/js';
|
import tsParser from "@typescript-eslint/parser";
|
||||||
import { FlatCompat } from '@eslint/eslintrc';
|
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 __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
@@ -16,15 +19,15 @@ const compat = new FlatCompat({
|
|||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
ignores: ['**/.eslintrc.js'],
|
ignores: ["**/.eslintrc.js"],
|
||||||
},
|
},
|
||||||
...compat.extends(
|
...compat.extends(
|
||||||
'plugin:@typescript-eslint/recommended-type-checked',
|
"plugin:@typescript-eslint/recommended-type-checked",
|
||||||
'plugin:prettier/recommended',
|
"plugin:prettier/recommended"
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
plugins: {
|
plugins: {
|
||||||
'@typescript-eslint': typescriptEslintEslintPlugin,
|
"@typescript-eslint": typescriptEslintEslintPlugin,
|
||||||
},
|
},
|
||||||
|
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
@@ -35,27 +38,27 @@ export default [
|
|||||||
|
|
||||||
parser: tsParser,
|
parser: tsParser,
|
||||||
ecmaVersion: 5,
|
ecmaVersion: 5,
|
||||||
sourceType: 'module',
|
sourceType: "module",
|
||||||
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: 'tsconfig.json',
|
project: "tsconfig.json",
|
||||||
tsconfigRootDir: '/home/legonzaur/Documents/code/concept/back',
|
tsconfigRootDir: __dirname,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/interface-name-prefix': 'off',
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
'require-await': 'off',
|
"require-await": "off",
|
||||||
'@typescript-eslint/require-await': 'error',
|
"@typescript-eslint/require-await": "error",
|
||||||
'@typescript-eslint/no-unused-vars': [
|
"@typescript-eslint/no-unused-vars": [
|
||||||
'warn',
|
"warn",
|
||||||
{
|
{
|
||||||
argsIgnorePattern: '^_',
|
argsIgnorePattern: "^_",
|
||||||
varsIgnorePattern: '^_',
|
varsIgnorePattern: "^_",
|
||||||
caughtErrorsIgnorePattern: '^_',
|
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": "latest",
|
||||||
"vue-multiselect": "^3.1.0",
|
"vue-multiselect": "^3.1.0",
|
||||||
"vue-router": "latest"
|
"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 newConcept = ref("");
|
||||||
const conceptStore = useConceptStore();
|
const conceptStore = useConceptStore();
|
||||||
|
|
||||||
await conceptStore.fetchConceptList();
|
await Promise.all([
|
||||||
|
conceptStore.fetchConceptList()
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const conceptInput = ref<HTMLInputElement | null>(null);
|
const conceptInput = ref<HTMLInputElement | null>(null);
|
||||||
@@ -49,25 +52,18 @@ onUnmounted(() => {
|
|||||||
<span>Delete</span>
|
<span>Delete</span>
|
||||||
<span>Type</span>
|
<span>Type</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="concept" v-for="concept in conceptStore.concepts" :key="concept.id">
|
||||||
class="concept"
|
|
||||||
v-for="concept in conceptStore.concepts"
|
|
||||||
:key="concept.id"
|
|
||||||
>
|
|
||||||
<span>{{ concept.value }}</span>
|
<span>{{ concept.value }}</span>
|
||||||
<input type="checkbox" checked="true" disabled="true" />
|
<input type="checkbox" checked="true" disabled="true" />
|
||||||
<input type="button" value="Delete" @click="deleteConcept(concept.id)" />
|
<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>
|
||||||
<div class="new-concept">
|
<div class="new-concept">
|
||||||
<span>
|
<span>
|
||||||
<input
|
<input ref="conceptInput" type="text" :disabled="loading" @keypress.enter="createConcept"
|
||||||
ref="conceptInput"
|
v-model="newConcept" />
|
||||||
type="text"
|
|
||||||
:disabled="loading"
|
|
||||||
@keypress.enter="createConcept"
|
|
||||||
v-model="newConcept"
|
|
||||||
/>
|
|
||||||
<button :disabled="loading" @click="createConcept">Submit</button>
|
<button :disabled="loading" @click="createConcept">Submit</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,6 +80,7 @@ div.concept {
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
div.header {
|
div.header {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
|||||||
+31
-12
@@ -1,34 +1,54 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { subscribe } from "~/netcode";
|
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";
|
import { handlers } from "~/netcode/handlers/concept.handler";
|
||||||
|
|
||||||
export const useConceptStore = defineStore("concept", {
|
export const useConceptStore = defineStore("concept", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
concepts: {} as Record<string, ConceptResponseDTO>,
|
concepts: {} as Record<string, ConceptResponseDTO>,
|
||||||
eventSource: null as null | EventSource,
|
eventSource: null as null | EventSource,
|
||||||
|
conceptTypes: {} as Record<string, ConceptTypeResponseDTO>,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async subscribe() {
|
subscribe() {
|
||||||
this.eventSource = subscribe(`/concepts/subscribe`);
|
this.eventSource = subscribe(`/concepts/subscribe`);
|
||||||
this.eventSource.addEventListener("message", async (message) => {
|
this.eventSource.addEventListener("message", (message) => {
|
||||||
const data = JSON.parse(message.data);
|
const data = JSON.parse(message.data) as ConceptEvent;
|
||||||
const type = data.type as string;
|
const type = data.type;
|
||||||
if (type in handlers) {
|
if (type in handlers) {
|
||||||
handlers[type as keyof typeof handlers](data);
|
handlers[type as keyof typeof handlers](data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async close() {
|
close() {
|
||||||
this.eventSource?.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() {
|
async fetchConceptList() {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const data = await useFetch<ConceptResponseDTO[]>(
|
const data = await useFetch<ConceptResponseDTO[]>(
|
||||||
config.public.endpoint + `/concepts/all`,
|
config.public.endpoint + `/concepts/all`,
|
||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
if (data.data.value && !data.error.value) {
|
if (data.data.value && !data.error.value) {
|
||||||
for (const concept of data.data.value) {
|
for (const concept of data.data.value) {
|
||||||
@@ -44,7 +64,7 @@ export const useConceptStore = defineStore("concept", {
|
|||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
// word.enabled = true;
|
// word.enabled = true;
|
||||||
// return data;
|
// return data;
|
||||||
@@ -56,12 +76,11 @@ export const useConceptStore = defineStore("concept", {
|
|||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
// word.enabled = false;
|
// word.enabled = false;
|
||||||
// return data;
|
// return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
async createConcept(value: string) {
|
async createConcept(value: string) {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const data = await $fetch<ConceptResponseDTO>(
|
const data = await $fetch<ConceptResponseDTO>(
|
||||||
@@ -70,7 +89,7 @@ export const useConceptStore = defineStore("concept", {
|
|||||||
credentials: "include",
|
credentials: "include",
|
||||||
body: { value },
|
body: { value },
|
||||||
method: "POST",
|
method: "POST",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async deleteConcept(id: number) {
|
async deleteConcept(id: number) {
|
||||||
@@ -80,7 +99,7 @@ export const useConceptStore = defineStore("concept", {
|
|||||||
{
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user