diff --git a/.idea/PHP_progettoPrimoQuadrimestre.iml b/.idea/PHP_progettoPrimoQuadrimestre.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/PHP_progettoPrimoQuadrimestre.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..186d49a
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..b6f58a7
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
new file mode 100644
index 0000000..f324872
--- /dev/null
+++ b/.idea/php.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/backend/Dockerfile b/backend/Dockerfile
new file mode 100644
index 0000000..7f69413
--- /dev/null
+++ b/backend/Dockerfile
@@ -0,0 +1,9 @@
+FROM php:8.2-apache
+
+RUN docker-php-ext-install mysqli pdo pdo_mysql
+
+RUN a2enmod rewrite
+
+COPY . /var/www/html/
+
+WORKDIR /var/www/html
diff --git a/backend/api/search.php b/backend/api/search.php
new file mode 100644
index 0000000..db602b5
--- /dev/null
+++ b/backend/api/search.php
@@ -0,0 +1,22 @@
+num_rows == 0) {
+ echo "Utente " . $username . " non trovato";
+ return;
+} else {
+ echo json_encode(array_values($result->fetch_assoc()));
+
+}
+
+?>
\ No newline at end of file
diff --git a/backend/config/database-connection.php b/backend/config/database-connection.php
new file mode 100644
index 0000000..d3f183c
--- /dev/null
+++ b/backend/config/database-connection.php
@@ -0,0 +1,7 @@
+query($query);
+ }
+}
\ No newline at end of file
diff --git a/backend/services/Search.php b/backend/services/Search.php
new file mode 100644
index 0000000..6d214f0
--- /dev/null
+++ b/backend/services/Search.php
@@ -0,0 +1,23 @@
+prepare($query);
+ $stmt->bind_param("s", $username);
+ $stmt->execute();
+ $result = $stmt->get_result();
+ return $result;
+ }
+
+}
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index dfdc738..31d415c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -12,10 +12,10 @@ services:
- backend
backend:
- image: php:8.2-apache
+ build: ./backend
container_name: libreria-php-backend
ports:
- - "8000:80" # PHP server
+ - "8000:80"
volumes:
- ./backend:/var/www/html
depends_on:
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index 175ac6e..58a7802 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:21
+FROM node:20
LABEL authors="Sergio Bianchi"
WORKDIR /app
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 75620b6..9eab6fb 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -9,7 +9,9 @@
"version": "0.0.0",
"dependencies": {
"react": "^19.1.1",
- "react-dom": "^19.1.1"
+ "react-dom": "^19.1.1",
+ "react-router": "^7.9.4",
+ "react-router-dom": "^7.9.4"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
@@ -57,7 +59,6 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
@@ -1428,7 +1429,6 @@
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -1439,7 +1439,6 @@
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -1500,7 +1499,6 @@
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2",
@@ -1753,7 +1751,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1872,7 +1869,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
@@ -1969,6 +1965,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2094,7 +2099,6 @@
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -2915,7 +2919,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2942,6 +2945,44 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.9.4",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.4.tgz",
+ "integrity": "sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.9.4",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.4.tgz",
+ "integrity": "sha512-f30P6bIkmYvnHHa5Gcu65deIXoA2+r3Eb6PJIAddvsT9aGlchMatJ51GgpU470aSqRRbFX22T70yQNUGuW3DfA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.9.4"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3045,6 +3086,12 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -3145,7 +3192,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -3198,7 +3244,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3285,7 +3330,6 @@
"integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -3379,7 +3423,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
diff --git a/frontend/package.json b/frontend/package.json
index d7f4bdb..7028562 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -11,7 +11,9 @@
},
"dependencies": {
"react": "^19.1.1",
- "react-dom": "^19.1.1"
+ "react-dom": "^19.1.1",
+ "react-router": "^7.9.4",
+ "react-router-dom": "^7.9.4"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
diff --git a/frontend/src/App.css b/frontend/src/App.css
deleted file mode 100644
index b9d355d..0000000
--- a/frontend/src/App.css
+++ /dev/null
@@ -1,42 +0,0 @@
-#root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.react:hover {
- filter: drop-shadow(0 0 2em #61dafbaa);
-}
-
-@keyframes logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-@media (prefers-reduced-motion: no-preference) {
- a:nth-of-type(2) .logo {
- animation: logo-spin infinite 20s linear;
- }
-}
-
-.card {
- padding: 2em;
-}
-
-.read-the-docs {
- color: #888;
-}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 3d7ded3..1d2e1cb 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,35 +1,30 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from '/vite.svg'
-import './App.css'
+import {useState} from 'react'
+import Topbar from "./components/Topbar.tsx"
+import Login from "./components/Login.tsx"
+import {BrowserRouter, Routes, Route} from "react-router-dom";
+
function App() {
- const [count, setCount] = useState(0)
- return (
- <>
-
- Vite + React
-
-
-
- Edit src/App.tsx and save to test HMR
-
-
-
- Click on the Vite and React logos to learn more
-
- >
- )
+ return (
+ <>
+
+
+
+
+
+ >
+ }/>
+
+
+ >
+ }/>
+
+
+ >
+ )
}
export default App
diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx
new file mode 100644
index 0000000..730db32
--- /dev/null
+++ b/frontend/src/components/Login.tsx
@@ -0,0 +1,27 @@
+import React from "react";
+import '../styles/login.css'
+
+
+function Login() {
+ return (
+ <>
+
+
+ >
+
+ );
+}
+
+export default Login
\ No newline at end of file
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
new file mode 100644
index 0000000..c3e646d
--- /dev/null
+++ b/frontend/src/components/Navbar.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+
+function Navbar(props) {
+ return (
+
+ );
+}
+
+export default Navbar
\ No newline at end of file
diff --git a/frontend/src/components/Topbar.tsx b/frontend/src/components/Topbar.tsx
new file mode 100644
index 0000000..bf0d768
--- /dev/null
+++ b/frontend/src/components/Topbar.tsx
@@ -0,0 +1,57 @@
+import React, {useRef, useState} from "react";
+
+function Topbar() {
+
+ const [isSearchCollapsed, setIsSearchCollapsed] = useState(true)
+ const [searchQuery, setSearchQuery] = useState('')
+ const searchInputRef = useRef(null)
+ const handleSearchButton = () => {
+ alert("search button clicked")
+ }
+
+ const handleSearchKeyDown = (event: React.KeyboardEvent) => {
+ if (event.key === "Enter") {
+ alert("Searching")
+ }
+ }
+
+ return (
+ <>
+
+ >
+ )
+}
+
+export default Topbar
\ No newline at end of file
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 08a3ac9..f6a28a9 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,68 +1,11 @@
:root {
- font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ font-family: Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
-body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
-}
+}
\ No newline at end of file
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index bef5202..0bfd0f6 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,10 +1,13 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
+import {StrictMode} from 'react'
+import {createRoot} from 'react-dom/client'
import './index.css'
+import './styles/topbar.css'
+import './styles/base.css'
import App from './App.tsx'
+import Topbar from "./components/Topbar.tsx";
createRoot(document.getElementById('root')!).render(
-
-
- ,
+
+
+
)
diff --git a/frontend/src/styles/base.css b/frontend/src/styles/base.css
new file mode 100644
index 0000000..3595af1
--- /dev/null
+++ b/frontend/src/styles/base.css
@@ -0,0 +1,5 @@
+body {
+ width: 100%;
+ padding: 0;
+ margin: 0;
+}
\ No newline at end of file
diff --git a/frontend/src/styles/login.css b/frontend/src/styles/login.css
new file mode 100644
index 0000000..21c3822
--- /dev/null
+++ b/frontend/src/styles/login.css
@@ -0,0 +1,80 @@
+:root {
+ --login-button-1: #414fcb;
+ --login-button-2: rgb(255, 255, 255);
+ --login-background: rgb(220, 220, 220);
+}
+
+#login-form-container {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -70%);
+ width: 500px;
+ height: 400px;
+ border: 1px solid black;
+ box-shadow: 2px 2px 2px grey;
+ border-radius: 20px;
+ margin: auto;
+ background: white;
+ display: flex;
+ flex-direction: column;
+}
+
+#login-form-container > * {
+ margin: 0;
+ flex-grow: 10;
+}
+
+#login-form-container > form {
+ display: flex;
+ flex-direction: column;
+}
+
+#login-form-container > form > .spacer-50 {
+ height: 50px;
+}
+
+#login-form-container > form > input {
+ width: 60%;
+ height: 40px;
+ margin: 10px auto;
+ border: none;
+ font-size: 20px;
+ border-bottom: 1px solid black;
+}
+
+#login-form-container > form > button {
+ width: 30%;
+ height: 50px;
+ margin: auto;
+ border-radius: 20px;
+ border: none;
+ background: var(--login-button-1);
+ color: var(--login-button-2);
+ font-size: 20px;
+}
+
+#login-form-container > form > button:hover {
+ background: var(--login-button-2);
+ color: var(--login-button-1);
+ border: 1px solid var(--login-button-1);
+ cursor: pointer;
+}
+
+#login-form-container > h1 {
+ flex-grow: 1;
+ margin-top: 10px;
+ align-content: center;
+ text-align: center;
+}
+
+#login-form-container > form {
+
+}
+
+#login-container {
+ background: var(--login-background);
+ width: 100vw;
+ height: 100vh;
+}
+
diff --git a/frontend/src/styles/topbar.css b/frontend/src/styles/topbar.css
new file mode 100644
index 0000000..aa1665d
--- /dev/null
+++ b/frontend/src/styles/topbar.css
@@ -0,0 +1,71 @@
+.topbar {
+ height: 70px;
+ width: 100%;
+ box-shadow: 0 1px 10px grey;
+ display: inline-flex;
+
+}
+
+.topbar-container {
+ height: 100%;
+ flex-grow: 1;
+ display: flex;
+ align-content: center;
+ align-items: center;
+}
+
+.topbar-container > .hamburger {
+ width: 20px;
+}
+
+.topbar-spacer-10 {
+ width: 10px;
+ height: 100%;
+}
+.topbar-spacer-20 {
+ width: 20px;
+ height: 100%;
+}
+.topbar-spacer-50 {
+ width: 20px;
+ height: 100%;
+}
+
+
+.topbar-search {
+ border: 1px solid black;
+ height: 30px;
+ width: 200px;
+ border-radius: 20px;
+ display: inline-flex;
+ align-items: center;
+}
+.topbar-search > input {
+ height: 25px;
+ border: 0;
+}
+.topbar-search > input:focus {
+ border: 0;
+ outline: none;
+}
+.topbar-search-button {
+ width: 50px;
+}
+.topbar-search-button:hover {
+ cursor: pointer;
+}
+
+#topbar-left {
+ display: inline-flex;
+}
+
+#topbar-right {
+ display: inline-flex;
+ flex-direction: row-reverse;
+}
+
+
+a:hover{
+ cursor: pointer;
+ color: blue;
+}
\ No newline at end of file
diff --git a/frontend/src/utils/api.ts b/frontend/src/utils/api.ts
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/utils/auth.ts b/frontend/src/utils/auth.ts
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/views/auth/placeholder.tsx b/frontend/src/views/auth/placeholder.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..1c490db
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6 @@
+{
+ "name": "PHP_progettoPrimoQuadrimestre",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {}
+}