diff --git a/backend/src/controllers/mods.js b/backend/src/controllers/mods.js
index d1f36dc..840ce08 100644
--- a/backend/src/controllers/mods.js
+++ b/backend/src/controllers/mods.js
@@ -43,7 +43,7 @@ async function getModByName(req, res) {
try {
// Query
const name = req.params.name
- const query_result = await mod_service.getModByName(name);
+ const query_result = await mod_service.getFullModInfos(name);
res.json(query_result);
} catch (error) {
handleError(error, res);
diff --git a/backend/src/models/mod.js b/backend/src/models/mod.js
index f7abfd9..6bfd051 100644
--- a/backend/src/models/mod.js
+++ b/backend/src/models/mod.js
@@ -14,24 +14,25 @@ async function getModByName(name) {
}
-async function getModFullInfos(name) {
+async function getFullModInfos(name) {
// Query
const base_infos = db.query(`SELECT * FROM Mods WHERE name = ?`, [name]);
const other_infos = db.query(`SELECT full_description, license, links, creation_date, downloads_count
- FROM ModInfos WHERE name = ?`, [name]);
- const tags = getModTags(name);
+ FROM ModInfos WHERE mod = ?`, [name]);
+ const tags = listTags(name);
- // Merge
- const res = {...await base_infos, ...await other_infos, ...tags};
-
- return res;
+ return [await base_infos, await other_infos, await tags];
}
async function listVersions(mod_name) {
return await db.query("SELECT * FROM ModVersions WHERE mod = ?", [mod_name]);
}
+async function listTags(mod_name) {
+ return await db.query(`SELECT tag FROM ModTags WHERE mod = ?`, [mod_name]);
+}
+
async function getVersionByNumber(mod_name, version_number) {
return await db.query(`SELECT * FROM ModVersions
WHERE mod = ?
@@ -184,8 +185,8 @@ async function containsTag(name, tag) {
// --- Exports ---
-module.exports = { getAllMods, getModByName, getModFullInfos,
- listVersions, getVersionByNumber, getVersion,
+module.exports = { getAllMods, getModByName, getFullModInfos,
+ listVersions, listTags, getVersionByNumber, getVersion,
createMod, addVersion, addTags,
updateMod,
deleteMod, deleteVersion, deleteTags,
diff --git a/backend/src/services/modService.js b/backend/src/services/modService.js
index 4cd8862..758db49 100644
--- a/backend/src/services/modService.js
+++ b/backend/src/services/modService.js
@@ -12,7 +12,7 @@ async function getAllMods() {
}
async function getModByName(name) {
- const res = model.getModByName(name);
+ const res = await model.getModByName(name);
if (res.length == 0) {
throw new AppError(404, "Cannot find mod with this name", "Not found");
}
@@ -20,16 +20,20 @@ async function getModByName(name) {
}
async function getFullModInfos(name) {
- const res = model.getFullModInfos(name);
- if (res.length == 0) {
- throw new AppError(404, "Cannot find mod with this name", "Not found");
+ const [base_infos, other_infos, tags] = await model.getFullModInfos(name);
+ // Check
+ if (base_infos.length == 0 || other_infos.length === 0) {
+ throw new AppError(404, "Cannot find mod with this name", "Not found", "Couldn't retrieve from database correctly");
}
- return res[0];
+ // Merge
+ const mod_infos = {...other_infos[0], tags: tags}
+ const res = {...base_infos[0], mod_infos: mod_infos};
+ return res;
}
async function getModVersion(infos) {
const { mod, version_number, game_version, platform, environment} = infos;
- const res = model.getModVersion(mod, version_number, game_version, platform, environment);
+ const res = await model.getModVersion(mod, version_number, game_version, platform, environment);
if (res.length == 0) {
throw new AppError(404, "Cannot find mod with this name", "Not found");
}
@@ -51,7 +55,7 @@ async function createMod(mod_data, author) {
mod_infos.full_description = await mdToHtml(mod_infos.full_description); // Convert
await sanitizeModData(mod_data); // Sanitize
//TODO
- mod_infos.creation_date = 0
+ mod_infos.creation_date = Date.now();
// Write changes to database
await model.createMod(name, display_name, author, description, mod_infos);
diff --git a/frontend/src/app.jsx b/frontend/src/app.jsx
index 5e1bbed..b61c897 100644
--- a/frontend/src/app.jsx
+++ b/frontend/src/app.jsx
@@ -7,8 +7,11 @@ import { Router } from 'preact-router';
// Pages
import HomePage from './pages/home';
import ModsPage from './pages/mods';
-// import AboutPage from './pages/about';
+import ModpacksPage from './pages/modpacks';
+import AboutPage from './pages/about';
import SettingsPage from './pages/settings';
+import ModPage from './pages/mod_page'
+import ModCreationPage from './pages/mod_creation'
// Components
import NavBar from './components/NavBar/navbar'
@@ -30,8 +33,12 @@ export function App() {
- {/* */}
+
+
+
+
+
diff --git a/frontend/src/assets/example.jpg b/frontend/src/assets/example.jpg
new file mode 100644
index 0000000..62eaab9
Binary files /dev/null and b/frontend/src/assets/example.jpg differ
diff --git a/frontend/src/assets/favorite.svg b/frontend/src/assets/favorite.svg
new file mode 100644
index 0000000..01a36da
--- /dev/null
+++ b/frontend/src/assets/favorite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/profile.svg b/frontend/src/assets/profile.svg
new file mode 100644
index 0000000..7bc75ae
--- /dev/null
+++ b/frontend/src/assets/profile.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/components/Buttons/button.jsx b/frontend/src/components/Buttons/button.jsx
index 99bfec9..105f156 100644
--- a/frontend/src/components/Buttons/button.jsx
+++ b/frontend/src/components/Buttons/button.jsx
@@ -1,18 +1,20 @@
import { h } from 'preact' // Necessary ?
import styles from './button.module.css'
-function Button({ children, onClick, className, variant = 'primary', ...rest}) {
+function Button({ children, onClick, href, className, variant = 'primary', ...rest}) {
const buttonClasses = `${styles.button} ${styles[variant] || ''} ${className || ''}`
return (
-
+
+
+
)
}
diff --git a/frontend/src/components/Buttons/button.module.css b/frontend/src/components/Buttons/button.module.css
index eefaec6..b8688b5 100644
--- a/frontend/src/components/Buttons/button.module.css
+++ b/frontend/src/components/Buttons/button.module.css
@@ -13,6 +13,10 @@
transition: 300ms;
}
+.button:hover {
+ cursor: pointer;
+}
+
.primary {
background-color: #353be5;
border-color: #4e53dc;
diff --git a/frontend/src/components/Buttons/checkbox.jsx b/frontend/src/components/Buttons/checkbox.jsx
index e69de29..3314b32 100644
--- a/frontend/src/components/Buttons/checkbox.jsx
+++ b/frontend/src/components/Buttons/checkbox.jsx
@@ -0,0 +1,38 @@
+//TODO made by AI
+import { h } from 'preact';
+import { useState } from 'preact/hooks';
+import styles from './checkbox.module.css';
+
+function Checkbox({ id, name, value, checked: initialChecked, onChange, label }) {
+ const [isChecked, setIsChecked] = useState(initialChecked || false);
+
+ const handleChange = (event) => {
+ setIsChecked(event.target.checked);
+ if (onChange) {
+ onChange(event); // Propagate the change event
+ }
+ };
+
+ return (
+
+
+
+
+ );
+}
+
+export default Checkbox;
\ No newline at end of file
diff --git a/frontend/src/components/Buttons/checkbox.module.css b/frontend/src/components/Buttons/checkbox.module.css
index e69de29..1043526 100644
--- a/frontend/src/components/Buttons/checkbox.module.css
+++ b/frontend/src/components/Buttons/checkbox.module.css
@@ -0,0 +1,51 @@
+/*TODO made by AI */
+.checkboxContainer {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ user-select: none; /* Prevent text selection on click */
+}
+
+.nativeCheckbox {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 0;
+ width: 0;
+}
+
+.customCheckbox {
+ position: relative;
+ display: inline-block;
+ width: 20px; /* Adjust size as needed */
+ height: 20px;
+ background-color: #eee;
+ border: 1px solid #ccc;
+ border-radius: 3px; /* Optional rounded corners */
+}
+
+.customCheckbox:hover input ~ .checkmark {
+ background-color: #ddd;
+}
+
+.nativeCheckbox:checked ~ .customCheckbox {
+ background-color: #2196F3; /* Active color */
+ border: 1px solid #2196F3;
+}
+
+.checkmark {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: white; /* Checkmark color */
+ font-size: 16px; /* Adjust checkmark size */
+}
+
+.label {
+ margin-left: 8px;
+}
\ No newline at end of file
diff --git a/frontend/src/components/Cards/row.jsx b/frontend/src/components/Cards/row.jsx
index 7955952..dade80a 100644
--- a/frontend/src/components/Cards/row.jsx
+++ b/frontend/src/components/Cards/row.jsx
@@ -9,18 +9,19 @@ import Thumbnail from '../../assets/mod.svg'
import DownloadIcon from '../../assets/download_alt.svg'
function GridCard({item}) {
+ const item_page = "/mods/" + item.name;
return (
-
-
-
+
+
+
{item.description}
-