frontend structiure generated
This commit is contained in:
8
wagfarm-ui/Dockerfile
Normal file
8
wagfarm-ui/Dockerfile
Normal 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
39
wagfarm-ui/css/forms.css
Normal 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
120
wagfarm-ui/css/style.css
Normal 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
86
wagfarm-ui/index.html
Normal 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 © 2025</p>
|
||||
</footer>
|
||||
|
||||
<script type="module" src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
64
wagfarm-ui/js/api.js
Normal file
64
wagfarm-ui/js/api.js
Normal 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
109
wagfarm-ui/js/app.js
Normal 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);
|
||||
}
|
||||
0
wagfarm-ui/js/entities/assets.js
Normal file
0
wagfarm-ui/js/entities/assets.js
Normal file
102
wagfarm-ui/js/entities/logs.js
Normal file
102
wagfarm-ui/js/entities/logs.js
Normal 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;
|
||||
0
wagfarm-ui/js/entities/taxonomy.js
Normal file
0
wagfarm-ui/js/entities/taxonomy.js
Normal file
0
wagfarm-ui/js/util.js
Normal file
0
wagfarm-ui/js/util.js
Normal file
Reference in New Issue
Block a user