first commit

This commit is contained in:
2025-09-17 18:55:33 +02:00
commit 232cd49052
29 changed files with 4705 additions and 0 deletions

8
front/.editorconfig Normal file
View File

@@ -0,0 +1,8 @@
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
max_line_length = 100

1
front/.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto eol=lf

30
front/.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

6
front/.prettierrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"singleQuote": true,
"printWidth": 100
}

8
front/.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"recommendations": [
"Vue.volar",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode"
]
}

3
front/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Personal Library Manager
Front of the application, made with Vue.js

26
front/eslint.config.js Normal file
View File

@@ -0,0 +1,26 @@
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
export default defineConfig([
{
name: 'app/files-to-lint',
files: ['**/*.{js,mjs,jsx,vue}'],
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
languageOptions: {
globals: {
...globals.browser,
},
},
},
js.configs.recommended,
...pluginVue.configs['flat/essential'],
skipFormatting,
])

14
front/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="css/bulma.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Personal Library Manager</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

8
front/jsconfig.json Normal file
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

4078
front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
front/package.json Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "personal-library-manager",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --fix",
"format": "prettier --write src/"
},
"dependencies": {
"vue": "^3.5.18"
},
"devDependencies": {
"@eslint/js": "^9.31.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/eslint-config-prettier": "^10.2.0",
"eslint": "^9.31.0",
"eslint-plugin-vue": "~10.3.0",
"globals": "^16.3.0",
"prettier": "3.6.2",
"vite": "^7.0.6",
"vite-plugin-vue-devtools": "^8.0.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

3
front/public/css/bulma.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
front/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

15
front/src/App.vue Normal file
View File

@@ -0,0 +1,15 @@
<script setup>
import BooksBrowser from './BooksBrowser.vue'
import AppNavBar from './AppNavBar.vue'
</script>
<template>
<header>
<AppNavBar/>
</header>
<main class="section">
<BooksBrowser/>
</main>
</template>
<style scoped></style>

41
front/src/AppNavBar.vue Normal file
View File

@@ -0,0 +1,41 @@
<script setup></script>
<template>
<nav class="navbar">
<div class="navbar-brand">
<div class="navbar-item">
PLM
</div>
</div>
<div class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item">
Home
</a>
<a class="navbar-item">
Books
</a>
<a class="navbar-item">
Locations
</a>
</div>
<div class="navbar-end">
</div>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<a class="button is-primary">
<strong>Sign up</strong>
</a>
<a class="button is-light">
Log in
</a>
</div>
</div>
</div>
</nav>
</template>
<style scoped></style>

48
front/src/BookCard.vue Normal file
View File

@@ -0,0 +1,48 @@
<script setup>
const props = defineProps({
title: String,
author: String,
imagePath: String,
rating: Number
});
const imagePathOrDefault = (props.imagePath == "" || typeof props.imagePath === 'undefined') ? "defaultbook.png" : props.imagePath;
</script>
<template>
<div class="box container has-background-dark">
<div class="media">
<div class="media-left">
<figure class="image mb-3">
<img v-bind:src="imagePathOrDefault" v-bind:alt="title">
</figure>
</div>
<div class="media-content">
<div class="is-size-4">{{title}}</div>
<div class="is-size-5 is-italic">{{author}}</div>
<p>{{rating}}/5</p>
</div>
</div>
</div>
</template>
<style scoped>
img {
max-height:200px;
max-width:200px;
height:auto;
width:auto;
}
.box {
transition:ease-in-out 0.04s
}
.box:hover {
transform: scale(1.01);
transition: ease-in-out 0.02s;
}
</style>

View File

@@ -0,0 +1,72 @@
<script setup>
import BookCard from './BookCard.vue';
import { useFetch } from './fetch.js'
const { data, error } = useFetch('http://localhost:8080/books');
console.log(data.value);
let books = [];
const dumas = {
id: 1,
title: "Le Comte de Monte-Cristo",
author: "Alexandre Dumas",
imagePath: "./comtemontecristo.png",
rating: 4.5
};
const celine = {
id: 2,
title: "Guerre",
author: "Céline",
imagePath: "",
rating: 5
}
const proust = {
id: 3,
title: "La Prisonnière",
author: "Marcel Proust",
imagePath: "",
rating: 5
}
const proust2 = {
id: 4,
title: "Du côté de chez Swann",
author: "Marcel Proust",
imagePath: "",
rating: 5
}
const balzac = {
id: 5,
title: "Splendeurs et misères des courtisanes",
author: "Balzac",
imagePath: "",
rating: 3
}
const cervantes = {
id: 6,
title: "LIngénieux Hidalgo Don Quichotte de la Manche ou L'Ingénieux Noble Don Quichotte de la Manche",
author: "Cervantès",
imagePath: "",
rating: 3
}
books.push(dumas);
books.push(celine);
books.push(proust);
books.push(proust2);
books.push(balzac);
books.push(cervantes);
</script>
<template>
<div class="grid">
<div v-if="error">Error when loading books: {{ error.message }}</div>
<div class="cell" v-else-if="data" v-for="book in data" :key="book.id">
<BookCard v-bind="book" />
</div>
<div v-else>Loading...</div>
</div>
</template>
<style scoped></style>

13
front/src/fetch.js Normal file
View File

@@ -0,0 +1,13 @@
import { ref } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
fetch(url)
.then((res) => res.json())
.then((json) => (data.value = json))
.catch((err) => (error.value = err))
return { data, error }
}

4
front/src/main.js Normal file
View File

@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

18
front/vite.config.js Normal file
View File

@@ -0,0 +1,18 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})