frontend structiure generated

This commit is contained in:
2025-04-17 17:00:15 +02:00
parent 22b6f3bd2a
commit 3ee632b683
15 changed files with 720 additions and 30 deletions

8
wagfarm-ui/Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
# Use Nginx as the base image
FROM nginx:alpine
# Copy the frontend files into the Nginx default directory
COPY ./ /usr/share/nginx/html
# Expose the default Nginx port (80)
EXPOSE 80

39
wagfarm-ui/css/forms.css Normal file
View File

@@ -0,0 +1,39 @@
/* forms.css */
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
input[type="text"],
input[type="date"],
textarea,
select {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 1rem;
}
textarea {
height: 100px;
}
button[type="submit"] {
background: #4a7c59;
color: white;
border: none;
padding: 0.7rem 1rem;
cursor: pointer;
font-size: 1rem;
border-radius: 3px;
}
button[type="submit"]:hover {
background: #3d6549;
}

120
wagfarm-ui/css/style.css Normal file
View File

@@ -0,0 +1,120 @@
/* styles.css */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
header {
background: #4a7c59;
color: #fff;
padding: 1rem;
}
header h1 {
margin-bottom: 1rem;
}
nav ul {
display: flex;
list-style: none;
}
nav ul li {
margin-right: 1rem;
}
nav ul li a {
color: #fff;
text-decoration: none;
padding: 0.5rem;
}
nav ul li a.active {
background: #fff;
color: #4a7c59;
border-radius: 3px;
}
.container {
display: flex;
max-width: 1200px;
margin: 0 auto;
padding: 1rem;
}
.sidebar {
flex: 1;
margin-right: 2rem;
}
.content {
flex: 3;
}
.log-item, .asset-item, .taxonomy-item {
border: 1px solid #ddd;
padding: 1rem;
margin-bottom: 1rem;
border-radius: 3px;
}
.actions {
margin-top: 0.5rem;
}
.actions button {
padding: 0.3rem 0.5rem;
margin-right: 0.5rem;
cursor: pointer;
}
.view-btn {
background: #4a7c59;
color: white;
border: none;
}
.edit-btn {
background: #f9a826;
color: white;
border: none;
}
.delete-btn {
background: #e74c3c;
color: white;
border: none;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 20px;
border-radius: 5px;
color: white;
z-index: 1000;
}
.notification.success {
background-color: #2ecc71;
}
.notification.error {
background-color: #e74c3c;
}
footer {
background: #333;
color: #fff;
text-align: center;
padding: 1rem;
margin-top: 2rem;
}

86
wagfarm-ui/index.html Normal file
View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Farm Work Tracker</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/forms.css">
</head>
<body>
<header>
<h1>Farm Work Tracker</h1>
<nav>
<ul>
<li><a href="#" class="nav-link active" data-entity="logs">Logs</a></li>
<li><a href="#" class="nav-link" data-entity="assets">Assets</a></li>
<li><a href="#" class="nav-link" data-entity="taxonomies">Taxonomies</a></li>
</ul>
</nav>
</header>
<main>
<div class="container">
<div class="sidebar">
<div id="logs-form-container" class="entity-form">
<h2>Create New Log</h2>
<form id="log-create-form">
<div class="form-group">
<label for="title">Title</label>
<input type="text" id="title" name="title" required>
</div>
<div class="form-group">
<label for="date">Date</label>
<input type="date" id="date" name="date" required>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description"></textarea>
</div>
<button type="submit">Create Log</button>
</form>
</div>
<div id="assets-form-container" class="entity-form" style="display: none;">
<h2>Create New Asset</h2>
<form id="asset-create-form">
<!-- Asset form fields -->
<button type="submit">Create Asset</button>
</form>
</div>
<div id="taxonomies-form-container" class="entity-form" style="display: none;">
<h2>Create New Taxonomy</h2>
<form id="taxonomy-create-form">
<!-- Taxonomy form fields -->
<button type="submit">Create Taxonomy</button>
</form>
</div>
</div>
<div class="content">
<div class="list-container">
<h2>Entity List</h2>
<div id="entity-list"></div>
</div>
<div class="detail-container">
<h2>Details</h2>
<div id="detail-view"></div>
</div>
<div class="edit-container" style="display: none;">
<h2>Edit</h2>
<div id="edit-form"></div>
</div>
</div>
</div>
</main>
<footer>
<p>Farm Work Tracker &copy; 2025</p>
</footer>
<script type="module" src="js/app.js"></script>
</body>
</html>

64
wagfarm-ui/js/api.js Normal file
View File

@@ -0,0 +1,64 @@
// api.js
const API = {
baseUrl: 'https://your-api-url.com/api',
async get(endpoint) {
try {
const response = await fetch(`${this.baseUrl}/${endpoint}`);
if (!response.ok) throw new Error(`API Error: ${response.status}`);
return await response.json();
} catch (error) {
console.error('GET request failed:', error);
throw error;
}
},
async post(endpoint, data) {
try {
const response = await fetch(`${this.baseUrl}/${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error(`API Error: ${response.status}`);
return await response.json();
} catch (error) {
console.error('POST request failed:', error);
throw error;
}
},
async put(endpoint, data) {
try {
const response = await fetch(`${this.baseUrl}/${endpoint}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error(`API Error: ${response.status}`);
return await response.json();
} catch (error) {
console.error('PUT request failed:', error);
throw error;
}
},
async delete(endpoint) {
try {
const response = await fetch(`${this.baseUrl}/${endpoint}`, {
method: 'DELETE'
});
if (!response.ok) throw new Error(`API Error: ${response.status}`);
return await response.json();
} catch (error) {
console.error('DELETE request failed:', error);
throw error;
}
}
};
export default API;

109
wagfarm-ui/js/app.js Normal file
View File

@@ -0,0 +1,109 @@
import LogsModule from './entities/logs.js';
import AssetsModule from './entities/assets.js';
import TaxonomiesModule from './entities/taxonomies.js';
// State to track which entity type is active
let activeEntityType = 'logs';
document.addEventListener('DOMContentLoaded', () => {
// Initialize navigation
setupNavigation();
// Load the default entity type
loadEntityList(activeEntityType);
// Setup form handlers
setupFormHandlers();
});
function setupNavigation() {
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const entityType = e.target.dataset.entity;
// Update active link
navLinks.forEach(l => l.classList.remove('active'));
e.target.classList.add('active');
// Update active entity and load data
activeEntityType = entityType;
loadEntityList(entityType);
// Show the appropriate form
document.querySelectorAll('.entity-form').forEach(form => {
form.style.display = 'none';
});
document.getElementById(`${entityType}-form-container`).style.display = 'block';
});
});
}
async function loadEntityList(entityType) {
// Clear previous content
document.getElementById('entity-list').innerHTML = '<p>Loading...</p>';
try {
let entities;
// Get data based on entity type
switch(entityType) {
case 'logs':
entities = await LogsModule.getAllLogs();
LogsModule.renderLogsList(entities, 'entity-list');
break;
case 'assets':
entities = await AssetsModule.getAllAssets();
AssetsModule.renderAssetsList(entities, 'entity-list');
break;
case 'taxonomies':
entities = await TaxonomiesModule.getAllTaxonomies();
TaxonomiesModule.renderTaxonomiesList(entities, 'entity-list');
break;
}
} catch (error) {
document.getElementById('entity-list').innerHTML = `<p>Error loading data: ${error.message}</p>`;
}
}
function setupFormHandlers() {
// Log creation form
document.getElementById('log-create-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const logData = {
title: formData.get('title'),
date: formData.get('date'),
description: formData.get('description')
// Add more fields as needed
};
try {
await LogsModule.createLog(logData);
e.target.reset();
if (activeEntityType === 'logs') {
loadEntityList('logs');
}
showNotification('Log created successfully');
} catch (error) {
showNotification(`Error: ${error.message}`, 'error');
}
});
// Add similar handlers for assets and taxonomies
}
function showNotification(message, type = 'success') {
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.textContent = message;
document.body.appendChild(notification);
// Remove after 3 seconds
setTimeout(() => {
notification.remove();
}, 3000);
}

View File

View File

@@ -0,0 +1,102 @@
// logs.js
import API from '../api.js';
const LogsModule = {
async getAllLogs() {
return await API.get('logs');
},
async getLog(id) {
return await API.get(`logs/${id}`);
},
async createLog(logData) {
return await API.post('logs', logData);
},
async updateLog(id, logData) {
return await API.put(`logs/${id}`, logData);
},
async deleteLog(id) {
return await API.delete(`logs/${id}`);
},
renderLogsList(logs, containerId) {
const container = document.getElementById(containerId);
container.innerHTML = '';
logs.forEach(log => {
const logElement = document.createElement('div');
logElement.className = 'log-item';
logElement.innerHTML = `
<h3>${log.title || 'Untitled Log'}</h3>
<p>${log.date || 'No date'}</p>
<div class="actions">
<button class="view-btn" data-id="${log.id}">View</button>
<button class="edit-btn" data-id="${log.id}">Edit</button>
<button class="delete-btn" data-id="${log.id}">Delete</button>
</div>
`;
container.appendChild(logElement);
});
// Add event listeners
this.addEventListeners(containerId);
},
addEventListeners(containerId) {
const container = document.getElementById(containerId);
container.addEventListener('click', async (e) => {
const id = e.target.dataset.id;
if (!id) return;
if (e.target.classList.contains('view-btn')) {
const log = await this.getLog(id);
// Display log details
document.getElementById('detail-view').innerHTML = `
<h2>${log.title || 'Untitled Log'}</h2>
<p>Date: ${log.date || 'No date'}</p>
<p>Description: ${log.description || 'No description'}</p>
<!-- Add more fields as needed -->
`;
} else if (e.target.classList.contains('edit-btn')) {
const log = await this.getLog(id);
// Populate edit form
document.getElementById('edit-form').innerHTML = `
<form id="log-edit-form" data-id="${log.id}">
<input type="text" name="title" value="${log.title || ''}">
<input type="date" name="date" value="${log.date || ''}">
<textarea name="description">${log.description || ''}</textarea>
<button type="submit">Save Changes</button>
</form>
`;
document.getElementById('log-edit-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const logData = {
title: formData.get('title'),
date: formData.get('date'),
description: formData.get('description')
};
await this.updateLog(id, logData);
// Refresh the list
const logs = await this.getAllLogs();
this.renderLogsList(logs, containerId);
});
} else if (e.target.classList.contains('delete-btn')) {
if (confirm('Are you sure you want to delete this log?')) {
await this.deleteLog(id);
// Refresh the list
const logs = await this.getAllLogs();
this.renderLogsList(logs, containerId);
}
}
});
}
};
export default LogsModule;

View File

0
wagfarm-ui/js/util.js Normal file
View File