Spaces:
Sleeping
Sleeping
features
Browse files- Dockerfile +2 -0
- database.db +0 -0
- main.py +16 -7
- models.py +1 -0
- static/app.js +105 -14
- static/styles.css +148 -78
- templates/edit_cables.html +2 -2
- templates/index.html +36 -21
Dockerfile
CHANGED
@@ -6,4 +6,6 @@ COPY . .
|
|
6 |
|
7 |
RUN pip install --no-cache-dir -r requirements.txt
|
8 |
|
|
|
|
|
9 |
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
6 |
|
7 |
RUN pip install --no-cache-dir -r requirements.txt
|
8 |
|
9 |
+
EXPOSE 7860
|
10 |
+
|
11 |
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
database.db
CHANGED
Binary files a/database.db and b/database.db differ
|
|
main.py
CHANGED
@@ -4,6 +4,7 @@ from fastapi.staticfiles import StaticFiles
|
|
4 |
from fastapi.templating import Jinja2Templates
|
5 |
from sqlalchemy.orm import Session
|
6 |
from pydantic import BaseModel
|
|
|
7 |
from models import Base, Cable, SessionLocal, init_db
|
8 |
|
9 |
app = FastAPI()
|
@@ -22,6 +23,9 @@ class VoltageDropRequest(BaseModel):
|
|
22 |
length: float
|
23 |
cable_type: str
|
24 |
|
|
|
|
|
|
|
25 |
def get_db():
|
26 |
db = SessionLocal()
|
27 |
try:
|
@@ -30,7 +34,9 @@ def get_db():
|
|
30 |
db.close()
|
31 |
|
32 |
def calculate_voltage_drop(voltage, load, length, resistance):
|
33 |
-
|
|
|
|
|
34 |
|
35 |
@app.get("/", response_class=HTMLResponse)
|
36 |
async def read_root(request: Request, db: Session = Depends(get_db)):
|
@@ -38,12 +44,15 @@ async def read_root(request: Request, db: Session = Depends(get_db)):
|
|
38 |
return templates.TemplateResponse("index.html", {"request": request, "cables": cables})
|
39 |
|
40 |
@app.post("/calculate")
|
41 |
-
async def calculate(request:
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
47 |
|
48 |
@app.get("/edit_cables", response_class=HTMLResponse)
|
49 |
async def edit_cables(request: Request, db: Session = Depends(get_db)):
|
|
|
4 |
from fastapi.templating import Jinja2Templates
|
5 |
from sqlalchemy.orm import Session
|
6 |
from pydantic import BaseModel
|
7 |
+
from typing import List
|
8 |
from models import Base, Cable, SessionLocal, init_db
|
9 |
|
10 |
app = FastAPI()
|
|
|
23 |
length: float
|
24 |
cable_type: str
|
25 |
|
26 |
+
class MultipleCablesRequest(BaseModel):
|
27 |
+
cables: List[VoltageDropRequest]
|
28 |
+
|
29 |
def get_db():
|
30 |
db = SessionLocal()
|
31 |
try:
|
|
|
34 |
db.close()
|
35 |
|
36 |
def calculate_voltage_drop(voltage, load, length, resistance):
|
37 |
+
voltage_drop = load * length * resistance
|
38 |
+
final_voltage = voltage - voltage_drop
|
39 |
+
return final_voltage
|
40 |
|
41 |
@app.get("/", response_class=HTMLResponse)
|
42 |
async def read_root(request: Request, db: Session = Depends(get_db)):
|
|
|
44 |
return templates.TemplateResponse("index.html", {"request": request, "cables": cables})
|
45 |
|
46 |
@app.post("/calculate")
|
47 |
+
async def calculate(request: MultipleCablesRequest, db: Session = Depends(get_db)):
|
48 |
+
results = []
|
49 |
+
for cable_request in request.cables:
|
50 |
+
cable = db.query(Cable).filter(Cable.type == cable_request.cable_type).first()
|
51 |
+
if not cable:
|
52 |
+
raise HTTPException(status_code=400, detail="Invalid cable type")
|
53 |
+
voltage_drop = calculate_voltage_drop(cable_request.voltage, cable_request.load, cable_request.length, cable.resistance)
|
54 |
+
results.append({"voltage_drop": voltage_drop})
|
55 |
+
return results
|
56 |
|
57 |
@app.get("/edit_cables", response_class=HTMLResponse)
|
58 |
async def edit_cables(request: Request, db: Session = Depends(get_db)):
|
models.py
CHANGED
@@ -2,6 +2,7 @@ from sqlalchemy import Column, Integer, String, Float, create_engine
|
|
2 |
from sqlalchemy.ext.declarative import declarative_base
|
3 |
from sqlalchemy.orm import sessionmaker
|
4 |
|
|
|
5 |
DATABASE_URL = "sqlite:///./database.db"
|
6 |
|
7 |
Base = declarative_base()
|
|
|
2 |
from sqlalchemy.ext.declarative import declarative_base
|
3 |
from sqlalchemy.orm import sessionmaker
|
4 |
|
5 |
+
#DATABASE_URL = "sqlite:///:memory:?check_same_thread=False" # Use this for in-memory database
|
6 |
DATABASE_URL = "sqlite:///./database.db"
|
7 |
|
8 |
Base = declarative_base()
|
static/app.js
CHANGED
@@ -1,6 +1,10 @@
|
|
1 |
document.addEventListener('DOMContentLoaded', function() {
|
2 |
const form = document.getElementById('calculator-form');
|
|
|
|
|
3 |
const calculateButton = document.querySelector('.btn-calculate');
|
|
|
|
|
4 |
|
5 |
// Function to check if all form fields are filled
|
6 |
function checkFormValidity() {
|
@@ -14,33 +18,120 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
14 |
}
|
15 |
}
|
16 |
|
17 |
-
//
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
-
//
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
// Handle form submission
|
24 |
form.addEventListener('submit', async function(event) {
|
25 |
event.preventDefault();
|
26 |
|
27 |
-
const formData = new FormData(
|
28 |
-
const
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
|
|
35 |
const response = await fetch('/calculate', {
|
36 |
method: 'POST',
|
37 |
headers: {
|
38 |
'Content-Type': 'application/json'
|
39 |
},
|
40 |
-
body: JSON.stringify(
|
41 |
});
|
42 |
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
});
|
|
|
|
|
|
|
|
|
|
|
46 |
});
|
|
|
1 |
document.addEventListener('DOMContentLoaded', function() {
|
2 |
const form = document.getElementById('calculator-form');
|
3 |
+
const cableContainer = document.getElementById('cable-container');
|
4 |
+
const addCableButton = document.getElementById('add-cable');
|
5 |
const calculateButton = document.querySelector('.btn-calculate');
|
6 |
+
let cableCount = 1;
|
7 |
+
const maxCables = 3;
|
8 |
|
9 |
// Function to check if all form fields are filled
|
10 |
function checkFormValidity() {
|
|
|
18 |
}
|
19 |
}
|
20 |
|
21 |
+
// Function to update the IDs and names of the inputs in each cable group
|
22 |
+
function updateCableGroupInputs() {
|
23 |
+
const cableGroups = document.querySelectorAll('.cable-group');
|
24 |
+
cableGroups.forEach((group, index) => {
|
25 |
+
group.querySelectorAll('input, select').forEach(input => {
|
26 |
+
// Update the id and name attributes to include the index
|
27 |
+
const baseName = input.name.split('[')[0]; // Get the base name without the index
|
28 |
+
input.name = `${baseName}[${index}]`;
|
29 |
+
input.id = `${baseName}-${index}`; // Update the id as well for accessibility
|
30 |
+
});
|
31 |
+
});
|
32 |
+
}
|
33 |
|
34 |
+
// Function to copy values from the first cable group
|
35 |
+
function copyInitialCableValues(newCableGroup) {
|
36 |
+
const initialCableGroup = document.querySelector('.cable-group');
|
37 |
+
|
38 |
+
// Copy values from the initial cable group to the new cable group
|
39 |
+
initialCableGroup.querySelectorAll('input, select').forEach((input, index) => {
|
40 |
+
const correspondingInput = newCableGroup.querySelectorAll('input, select')[index];
|
41 |
+
correspondingInput.value = input.value;
|
42 |
+
});
|
43 |
+
}
|
44 |
+
|
45 |
+
// Function to update the visibility of the remove buttons
|
46 |
+
function updateRemoveButtons() {
|
47 |
+
const removeButtons = document.querySelectorAll('.btn-remove-cable');
|
48 |
+
removeButtons.forEach(button => {
|
49 |
+
if (cableCount > 1) {
|
50 |
+
button.style.display = 'inline-block';
|
51 |
+
} else {
|
52 |
+
button.style.display = 'none';
|
53 |
+
}
|
54 |
+
});
|
55 |
+
}
|
56 |
+
|
57 |
+
// Add a new cable section
|
58 |
+
addCableButton.addEventListener('click', function() {
|
59 |
+
if (cableCount < maxCables) {
|
60 |
+
const newCableGroup = document.querySelector('.cable-group').cloneNode(true);
|
61 |
+
|
62 |
+
// Copy values from the initial cable group
|
63 |
+
copyInitialCableValues(newCableGroup);
|
64 |
+
|
65 |
+
// Append the new cable group to the container
|
66 |
+
cableContainer.appendChild(newCableGroup);
|
67 |
+
cableCount++;
|
68 |
+
updateCableGroupInputs();
|
69 |
+
updateRemoveButtons();
|
70 |
+
checkFormValidity();
|
71 |
+
}
|
72 |
+
if (cableCount >= maxCables) {
|
73 |
+
addCableButton.disabled = true;
|
74 |
+
}
|
75 |
+
});
|
76 |
+
|
77 |
+
// Remove a cable section
|
78 |
+
cableContainer.addEventListener('click', function(event) {
|
79 |
+
if (event.target.classList.contains('btn-remove-cable')) {
|
80 |
+
if (cableCount > 1) {
|
81 |
+
event.target.closest('.cable-group').remove();
|
82 |
+
cableCount--;
|
83 |
+
updateCableGroupInputs();
|
84 |
+
addCableButton.disabled = false;
|
85 |
+
updateRemoveButtons();
|
86 |
+
checkFormValidity();
|
87 |
+
}
|
88 |
+
}
|
89 |
+
});
|
90 |
|
91 |
// Handle form submission
|
92 |
form.addEventListener('submit', async function(event) {
|
93 |
event.preventDefault();
|
94 |
|
95 |
+
const formData = new FormData(form);
|
96 |
+
const cablesData = [];
|
97 |
+
|
98 |
+
// Iterate over the form data and collect all cables
|
99 |
+
for (let i = 0; i < cableCount; i++) {
|
100 |
+
const voltage = parseFloat(formData.get(`voltage[${i}]`));
|
101 |
+
const load = parseFloat(formData.get(`load[${i}]`));
|
102 |
+
const length = parseFloat(formData.get(`length[${i}]`));
|
103 |
+
const cable_type = formData.get(`cable_type[${i}]`);
|
104 |
+
|
105 |
+
cablesData.push({ voltage, load, length, cable_type });
|
106 |
+
}
|
107 |
+
|
108 |
+
console.log("Sending cables data:", cablesData); // Debugging line
|
109 |
|
110 |
+
// Send the cables data to the backend
|
111 |
const response = await fetch('/calculate', {
|
112 |
method: 'POST',
|
113 |
headers: {
|
114 |
'Content-Type': 'application/json'
|
115 |
},
|
116 |
+
body: JSON.stringify({ cables: cablesData })
|
117 |
});
|
118 |
|
119 |
+
if (response.ok) {
|
120 |
+
const results = await response.json();
|
121 |
+
|
122 |
+
// Display the results
|
123 |
+
let resultsHtml = '';
|
124 |
+
results.forEach((result, index) => {
|
125 |
+
resultsHtml += `<p>Cable ${index + 1}: Voltage Drop: ${result.voltage_drop.toFixed(2)} V</p>`;
|
126 |
+
});
|
127 |
+
document.getElementById('result').innerHTML = resultsHtml;
|
128 |
+
} else {
|
129 |
+
console.error("Error:", response.statusText);
|
130 |
+
}
|
131 |
});
|
132 |
+
|
133 |
+
// Initially check the form validity and update buttons on page load
|
134 |
+
form.addEventListener('input', checkFormValidity);
|
135 |
+
checkFormValidity();
|
136 |
+
updateRemoveButtons();
|
137 |
});
|
static/styles.css
CHANGED
@@ -1,11 +1,9 @@
|
|
|
|
1 |
body {
|
2 |
font-family: Arial, sans-serif;
|
3 |
-
|
4 |
-
flex-direction: column;
|
5 |
-
align-items: center;
|
6 |
margin: 0;
|
7 |
padding: 0;
|
8 |
-
background-color: #f8f9fa;
|
9 |
}
|
10 |
|
11 |
header {
|
@@ -18,68 +16,94 @@ header {
|
|
18 |
padding: 20px 0;
|
19 |
}
|
20 |
|
21 |
-
.calculator-form {
|
22 |
-
width: 100%;
|
23 |
-
display: flex;
|
24 |
-
flex-direction: column;
|
25 |
-
}
|
26 |
-
|
27 |
#logo {
|
28 |
height: 50px;
|
29 |
margin-right: 20px;
|
30 |
}
|
31 |
|
32 |
-
|
|
|
|
|
|
|
|
|
33 |
display: flex;
|
34 |
flex-direction: column;
|
35 |
align-items: center;
|
36 |
-
margin
|
37 |
width: 100%;
|
38 |
-
max-width:
|
39 |
padding: 20px;
|
40 |
-
|
41 |
-
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
42 |
-
border-radius: 8px;
|
43 |
}
|
44 |
|
45 |
-
|
46 |
-
|
|
|
|
|
47 |
width: 100%;
|
48 |
-
margin-bottom:
|
|
|
49 |
}
|
50 |
|
51 |
-
.
|
52 |
-
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
color: #343a40;
|
55 |
}
|
56 |
|
57 |
.form-row {
|
58 |
display: flex;
|
59 |
-
align-items: center;
|
60 |
justify-content: space-between;
|
|
|
61 |
margin-bottom: 15px;
|
|
|
62 |
}
|
63 |
|
64 |
.form-row label {
|
65 |
-
flex
|
66 |
font-weight: bold;
|
|
|
67 |
}
|
68 |
|
69 |
-
.form-row input
|
70 |
-
|
|
|
71 |
padding: 8px;
|
72 |
font-size: 16px;
|
73 |
border: 1px solid #ccc;
|
74 |
-
border-radius:
|
|
|
|
|
75 |
}
|
76 |
|
|
|
77 |
.form-row select {
|
78 |
-
|
|
|
79 |
padding: 8px;
|
80 |
font-size: 16px;
|
81 |
border: 1px solid #ccc;
|
82 |
-
border-radius:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
|
85 |
.btn {
|
@@ -89,88 +113,134 @@ main {
|
|
89 |
border: none;
|
90 |
color: white;
|
91 |
border-radius: 4px;
|
|
|
92 |
}
|
93 |
|
94 |
-
.btn
|
95 |
-
|
96 |
-
width: 100%;
|
97 |
}
|
98 |
|
99 |
-
.btn-
|
|
|
100 |
background-color: #007bff;
|
101 |
-
margin-right:
|
102 |
}
|
103 |
|
104 |
-
.btn-
|
105 |
-
background-color: #
|
|
|
106 |
}
|
107 |
|
108 |
-
.btn-
|
109 |
-
|
110 |
-
|
111 |
-
margin-top: 10px;
|
112 |
}
|
113 |
|
114 |
-
.
|
115 |
-
|
116 |
-
|
117 |
-
border-top: 2px solid #dee2e6;
|
118 |
-
width: 100%;
|
119 |
}
|
120 |
|
121 |
-
.cable
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
}
|
127 |
|
128 |
.btn-back {
|
129 |
background-color: #007bff;
|
130 |
color: white;
|
131 |
-
padding:
|
132 |
-
font-size:
|
133 |
text-align: center;
|
134 |
text-decoration: none;
|
135 |
-
margin-top:
|
136 |
-
display: inline-block;
|
137 |
-
border-radius: 5px;
|
138 |
-
width: 100%;
|
139 |
}
|
140 |
|
141 |
.btn-back:hover {
|
142 |
background-color: #0056b3;
|
143 |
}
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
text-align: center;
|
155 |
-
transition: background-color 0.3s ease;
|
156 |
}
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
}
|
162 |
|
163 |
-
.btn-
|
164 |
-
background-color: #
|
165 |
}
|
166 |
|
167 |
-
.
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
padding: 20px;
|
173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
width: 100%;
|
|
|
175 |
}
|
176 |
|
|
|
|
|
|
|
|
|
|
1 |
+
/* General Styles */
|
2 |
body {
|
3 |
font-family: Arial, sans-serif;
|
4 |
+
background-color: #f8f9fa;
|
|
|
|
|
5 |
margin: 0;
|
6 |
padding: 0;
|
|
|
7 |
}
|
8 |
|
9 |
header {
|
|
|
16 |
padding: 20px 0;
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
#logo {
|
20 |
height: 50px;
|
21 |
margin-right: 20px;
|
22 |
}
|
23 |
|
24 |
+
h1 {
|
25 |
+
margin: 0;
|
26 |
+
}
|
27 |
+
|
28 |
+
.calculator-main {
|
29 |
display: flex;
|
30 |
flex-direction: column;
|
31 |
align-items: center;
|
32 |
+
margin: 30px auto;
|
33 |
width: 100%;
|
34 |
+
max-width: 1200px;
|
35 |
padding: 20px;
|
36 |
+
box-sizing: border-box;
|
|
|
|
|
37 |
}
|
38 |
|
39 |
+
#cable-container {
|
40 |
+
display: flex;
|
41 |
+
gap: 20px;
|
42 |
+
justify-content: center;
|
43 |
width: 100%;
|
44 |
+
margin-bottom: 20px;
|
45 |
+
flex-wrap: wrap; /* Allow wrapping for better responsiveness */
|
46 |
}
|
47 |
|
48 |
+
.cable-group {
|
49 |
+
background-color: white;
|
50 |
+
padding: 20px;
|
51 |
+
border-radius: 8px;
|
52 |
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
53 |
+
box-sizing: border-box;
|
54 |
+
position: relative;
|
55 |
+
flex: auto; /* Let the items grow and shrink based on space */
|
56 |
+
max-width: 800px; /* Optional maximum width */
|
57 |
+
min-width: 500px; /* Optional minimum width */
|
58 |
+
}
|
59 |
+
|
60 |
+
.cable-group h2 {
|
61 |
+
text-align: center;
|
62 |
+
margin-top: 0;
|
63 |
color: #343a40;
|
64 |
}
|
65 |
|
66 |
.form-row {
|
67 |
display: flex;
|
|
|
68 |
justify-content: space-between;
|
69 |
+
align-items: center;
|
70 |
margin-bottom: 15px;
|
71 |
+
width: 100%;
|
72 |
}
|
73 |
|
74 |
.form-row label {
|
75 |
+
flex: 0 0 40%; /* Label takes up 40% of the row */
|
76 |
font-weight: bold;
|
77 |
+
color: #343a40;
|
78 |
}
|
79 |
|
80 |
+
.form-row input,
|
81 |
+
.form-row select {
|
82 |
+
flex: 1; /* Input takes up the remaining space */
|
83 |
padding: 8px;
|
84 |
font-size: 16px;
|
85 |
border: 1px solid #ccc;
|
86 |
+
border-radius: 4px;
|
87 |
+
width: 100%;
|
88 |
+
box-sizing: border-box;
|
89 |
}
|
90 |
|
91 |
+
/* Dropdown styling */
|
92 |
.form-row select {
|
93 |
+
appearance: none;
|
94 |
+
background-color: #f8f9fa;
|
95 |
padding: 8px;
|
96 |
font-size: 16px;
|
97 |
border: 1px solid #ccc;
|
98 |
+
border-radius: 4px;
|
99 |
+
width: 100%;
|
100 |
+
box-sizing: border-box;
|
101 |
+
}
|
102 |
+
|
103 |
+
.btn-group, .form-group {
|
104 |
+
display: flex;
|
105 |
+
justify-content: space-between;
|
106 |
+
width: 100%; /* Ensure buttons are aligned in one row */
|
107 |
}
|
108 |
|
109 |
.btn {
|
|
|
113 |
border: none;
|
114 |
color: white;
|
115 |
border-radius: 4px;
|
116 |
+
transition: background-color 0.3s ease;
|
117 |
}
|
118 |
|
119 |
+
.btn:hover {
|
120 |
+
opacity: 0.9;
|
|
|
121 |
}
|
122 |
|
123 |
+
.btn-add,
|
124 |
+
.btn-add-cable {
|
125 |
background-color: #007bff;
|
126 |
+
margin-right: 10px;
|
127 |
}
|
128 |
|
129 |
+
.btn-add-cable:disabled {
|
130 |
+
background-color: #6c757d;
|
131 |
+
cursor: not-allowed;
|
132 |
}
|
133 |
|
134 |
+
.btn-calculate {
|
135 |
+
background-color: #6c757d; /* Disabled state */
|
136 |
+
cursor: not-allowed;
|
|
|
137 |
}
|
138 |
|
139 |
+
.btn-calculate.enabled {
|
140 |
+
background-color: #28a745; /* Enabled state */
|
141 |
+
cursor: pointer;
|
|
|
|
|
142 |
}
|
143 |
|
144 |
+
.btn-remove-cable {
|
145 |
+
background-color: #dc3545;
|
146 |
+
padding: 3px 8px;
|
147 |
+
font-size: 12px;
|
148 |
+
position: absolute;
|
149 |
+
bottom: 10px;
|
150 |
+
right: 10px;
|
151 |
+
}
|
152 |
+
|
153 |
+
.action-buttons {
|
154 |
+
display: flex;
|
155 |
+
justify-content: center;
|
156 |
+
gap: 10px;
|
157 |
width: 100%;
|
158 |
+
margin-bottom: 20px;
|
159 |
+
}
|
160 |
+
|
161 |
+
.result-display {
|
162 |
+
margin-top: 20px;
|
163 |
+
font-size: 20px;
|
164 |
+
color: #28a745;
|
165 |
+
text-align: center;
|
166 |
+
padding: 20px;
|
167 |
+
border-top: 2px solid #dee2e6;
|
168 |
+
width: 50%;
|
169 |
+
background-color: white;
|
170 |
+
border-radius: 8px;
|
171 |
+
box-sizing: border-box;
|
172 |
}
|
173 |
|
174 |
.btn-back {
|
175 |
background-color: #007bff;
|
176 |
color: white;
|
177 |
+
padding: 8px 16px;
|
178 |
+
font-size: 10px;
|
179 |
text-align: center;
|
180 |
text-decoration: none;
|
181 |
+
margin-top: 16px;
|
|
|
|
|
|
|
182 |
}
|
183 |
|
184 |
.btn-back:hover {
|
185 |
background-color: #0056b3;
|
186 |
}
|
187 |
+
|
188 |
+
/* Media Queries for Responsiveness */
|
189 |
+
@media (max-width: 992px) {
|
190 |
+
#cable-container .cable-group {
|
191 |
+
flex: 1 1 48%; /* Two cables per row on medium screens */
|
192 |
+
}
|
193 |
+
|
194 |
+
#cable-container .cable-group:nth-child(3) {
|
195 |
+
flex: 1 1 100%; /* Stack the third cable below on medium screens */
|
196 |
+
}
|
|
|
|
|
197 |
}
|
198 |
|
199 |
+
@media (max-width: 768px) {
|
200 |
+
#cable-container .cable-group {
|
201 |
+
flex: 1 1 100%; /* Full width for all cables on small screens */
|
202 |
+
}
|
203 |
+
|
204 |
+
.btn-add-cable,
|
205 |
+
.btn-calculate {
|
206 |
+
width: 100%;
|
207 |
+
margin-right: 0;
|
208 |
+
}
|
209 |
+
|
210 |
+
.action-buttons {
|
211 |
+
flex-direction: column;
|
212 |
+
}
|
213 |
}
|
214 |
|
215 |
+
.btn-save {
|
216 |
+
background-color: #007bff;
|
217 |
}
|
218 |
|
219 |
+
.btn-delete {
|
220 |
+
background-color: #dc3545;
|
221 |
+
}
|
222 |
+
|
223 |
+
/* Adjusted Specific Styles for the Edit Cables Page */
|
224 |
+
.edit-cables-main {
|
225 |
+
display: flex;
|
226 |
+
flex-direction: column;
|
227 |
+
align-items: center;
|
228 |
+
margin: 30px auto;
|
229 |
+
width: 100%;
|
230 |
+
max-width: 500px; /* Adjusted width to make it more compact */
|
231 |
padding: 20px;
|
232 |
+
box-sizing: border-box;
|
233 |
+
background-color: white;
|
234 |
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
235 |
+
border-radius: 8px;
|
236 |
+
}
|
237 |
+
|
238 |
+
.add-cable-section, .existing-cables-section {
|
239 |
width: 100%;
|
240 |
+
margin-bottom: 30px;
|
241 |
}
|
242 |
|
243 |
+
.add-cable-section h2, .existing-cables-section h2 {
|
244 |
+
margin-bottom: 20px;
|
245 |
+
color: #343a40;
|
246 |
+
}
|
templates/edit_cables.html
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
<header>
|
11 |
<h1>Edit Cables</h1>
|
12 |
</header>
|
13 |
-
<main>
|
14 |
<section class="add-cable-section">
|
15 |
<h2>Add Cable</h2>
|
16 |
<form action="/add_cable" method="post" class="cable-form">
|
@@ -43,7 +43,7 @@
|
|
43 |
<label for="resistance">Resistance:</label>
|
44 |
<input type="number" step="0.01" id="resistance" name="resistance" value="{{ cable.resistance }}" required>
|
45 |
</div>
|
46 |
-
<div class="
|
47 |
<button type="submit" class="btn btn-save">Save</button>
|
48 |
<button formaction="/delete_cable/{{ cable.id }}" formmethod="post" class="btn btn-delete">Delete</button>
|
49 |
</div>
|
|
|
10 |
<header>
|
11 |
<h1>Edit Cables</h1>
|
12 |
</header>
|
13 |
+
<main class="edit-cables-main">
|
14 |
<section class="add-cable-section">
|
15 |
<h2>Add Cable</h2>
|
16 |
<form action="/add_cable" method="post" class="cable-form">
|
|
|
43 |
<label for="resistance">Resistance:</label>
|
44 |
<input type="number" step="0.01" id="resistance" name="resistance" value="{{ cable.resistance }}" required>
|
45 |
</div>
|
46 |
+
<div class="btn-group">
|
47 |
<button type="submit" class="btn btn-save">Save</button>
|
48 |
<button formaction="/delete_cable/{{ cable.id }}" formmethod="post" class="btn btn-delete">Delete</button>
|
49 |
</div>
|
templates/index.html
CHANGED
@@ -12,36 +12,51 @@
|
|
12 |
<h1>Voltage Drop Calculator</h1>
|
13 |
</header>
|
14 |
<main class="calculator-main">
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
<
|
19 |
-
|
20 |
-
<
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
38 |
</div>
|
39 |
|
40 |
-
|
|
|
|
|
|
|
|
|
41 |
</form>
|
42 |
|
|
|
43 |
<div id="result" class="result-display"></div>
|
44 |
|
|
|
45 |
<a href="/edit_cables" class="btn btn-back">Edit Cables</a>
|
46 |
</main>
|
47 |
<script src="/static/app.js"></script>
|
|
|
12 |
<h1>Voltage Drop Calculator</h1>
|
13 |
</header>
|
14 |
<main class="calculator-main">
|
15 |
+
<!-- Form wraps all cable groups -->
|
16 |
+
<form id="calculator-form">
|
17 |
+
<div id="cable-container">
|
18 |
+
<div class="cable-group">
|
19 |
+
<h2>Cable 1</h2>
|
20 |
+
<div class="form-row">
|
21 |
+
<label for="cable_type-0">Cable Type:</label>
|
22 |
+
<select id="cable_type-0" name="cable_type[0]" required>
|
23 |
+
{% for cable in cables %}
|
24 |
+
<option value="{{ cable.type }}">{{ cable.type }}</option>
|
25 |
+
{% endfor %}
|
26 |
+
</select>
|
27 |
+
</div>
|
28 |
|
29 |
+
<div class="form-row">
|
30 |
+
<label for="voltage-0">Voltage:</label>
|
31 |
+
<input type="number" id="voltage-0" name="voltage[0]" required>
|
32 |
+
</div>
|
33 |
|
34 |
+
<div class="form-row">
|
35 |
+
<label for="load-0">Load (A):</label>
|
36 |
+
<input type="number" id="load-0" name="load[0]" required>
|
37 |
+
</div>
|
38 |
|
39 |
+
<div class="form-row">
|
40 |
+
<label for="length-0">Length (m):</label>
|
41 |
+
<input type="number" id="length-0" name="length[0]" required>
|
42 |
+
</div>
|
43 |
+
|
44 |
+
<!-- Remove Cable Button -->
|
45 |
+
<button type="button" class="btn btn-remove-cable" style="display: none;">- Remove Cable</button>
|
46 |
+
</div>
|
47 |
</div>
|
48 |
|
49 |
+
<!-- Action Buttons -->
|
50 |
+
<div class="action-buttons">
|
51 |
+
<button id="add-cable" type="button" class="btn btn-add-cable">+ Add Cable</button>
|
52 |
+
<button type="submit" class="btn btn-calculate">Calculate</button>
|
53 |
+
</div>
|
54 |
</form>
|
55 |
|
56 |
+
<!-- Results Display -->
|
57 |
<div id="result" class="result-display"></div>
|
58 |
|
59 |
+
<!-- Edit Cables Link -->
|
60 |
<a href="/edit_cables" class="btn btn-back">Edit Cables</a>
|
61 |
</main>
|
62 |
<script src="/static/app.js"></script>
|