first commit
This commit is contained in:
8
front/.editorconfig
Normal file
8
front/.editorconfig
Normal 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
1
front/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
30
front/.gitignore
vendored
Normal file
30
front/.gitignore
vendored
Normal 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
6
front/.prettierrc.json
Normal 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
8
front/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"Vue.volar",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
3
front/README.md
Normal file
3
front/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Personal Library Manager
|
||||
|
||||
Front of the application, made with Vue.js
|
||||
26
front/eslint.config.js
Normal file
26
front/eslint.config.js
Normal 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
14
front/index.html
Normal 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
8
front/jsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
4078
front/package-lock.json
generated
Normal file
4078
front/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
front/package.json
Normal file
30
front/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
BIN
front/public/comtemontecristo.png
Normal file
BIN
front/public/comtemontecristo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 750 KiB |
3
front/public/css/bulma.min.css
vendored
Normal file
3
front/public/css/bulma.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
front/public/defaultbook.png
Normal file
BIN
front/public/defaultbook.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
front/public/favicon.ico
Normal file
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
15
front/src/App.vue
Normal 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
41
front/src/AppNavBar.vue
Normal 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
48
front/src/BookCard.vue
Normal 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>
|
||||
72
front/src/BooksBrowser.vue
Normal file
72
front/src/BooksBrowser.vue
Normal 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: "L’Ingé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
13
front/src/fetch.js
Normal 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
4
front/src/main.js
Normal 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
18
front/vite.config.js
Normal 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))
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user