From d3ecfae5df8ee802b671b1fd91ce1f120ee7b206 Mon Sep 17 00:00:00 2001 From: Cyber Panel Date: Tue, 1 Jul 2025 11:43:34 +0200 Subject: [PATCH] feat: Add Uziomy calculator page with grounding calculations and document generation - Implemented Uziomy component for calculating grounding parameters. - Added state management for input fields and results. - Integrated DatePicker for date selection. - Created functions for grounding calculations, document generation (DOCX), and DXF file generation. - Enhanced UI with Tailwind CSS for better styling and responsiveness. - Updated global styles to include Inter font and custom scrollbar styles. - Configured Tailwind CSS to extend colors, fonts, and animations. --- UI_REDESIGN_PROPOSAL.md | 132 +++ archive/README.md | 39 + archive/components/templates/generator_old.js | 231 ++++++ archive/components/templates/manual_old.js | 157 ++++ archive/pages/cross_old.js | 178 +++++ archive/pages/uziomy_old.js | 551 +++++++++++++ components/templates/generator.js | 323 +++++--- components/templates/generator_new.js | 294 +++++++ components/templates/manual.js | 280 ++++--- components/templates/manual_new.js | 241 ++++++ components/ui/Layout.js | 154 ++++ components/ui/components.js | 179 +++++ package-lock.json | 291 +++---- package.json | 2 + pages/cross.js | 339 ++++---- pages/cross_new.js | 247 ++++++ pages/index.js | 191 +++-- pages/uziomy.js | 756 +++++++++--------- pages/uziomy_new.js | 545 +++++++++++++ styles/globals.css | 83 +- tailwind.config.js | 33 +- 21 files changed, 4224 insertions(+), 1022 deletions(-) create mode 100644 UI_REDESIGN_PROPOSAL.md create mode 100644 archive/README.md create mode 100644 archive/components/templates/generator_old.js create mode 100644 archive/components/templates/manual_old.js create mode 100644 archive/pages/cross_old.js create mode 100644 archive/pages/uziomy_old.js create mode 100644 components/templates/generator_new.js create mode 100644 components/templates/manual_new.js create mode 100644 components/ui/Layout.js create mode 100644 components/ui/components.js create mode 100644 pages/cross_new.js create mode 100644 pages/uziomy_new.js diff --git a/UI_REDESIGN_PROPOSAL.md b/UI_REDESIGN_PROPOSAL.md new file mode 100644 index 0000000..7ede914 --- /dev/null +++ b/UI_REDESIGN_PROPOSAL.md @@ -0,0 +1,132 @@ +# Wastpol UI Redesign Proposal + +## Overview +This UI redesign modernizes the Wastpol electrical engineering application with a contemporary, professional interface while maintaining all existing functionality. + +## Key Improvements + +### 🎨 **Visual Design** +- **Modern Color Palette**: Professional blue-based theme with proper contrast ratios +- **Typography**: Inter font family for improved readability +- **Consistent Spacing**: Systematic spacing scale using Tailwind CSS +- **Enhanced Shadows**: Subtle depth with layered shadow system +- **Better Visual Hierarchy**: Clear information architecture with proper heading levels + +### 📱 **Responsive Layout** +- **Mobile-First Design**: Optimized for all screen sizes +- **Sidebar Navigation**: Collapsible sidebar for desktop, drawer for mobile +- **Adaptive Grid**: Responsive card layouts that adjust to screen size +- **Touch-Friendly**: Proper touch targets for mobile devices + +### 🎯 **User Experience** +- **Simplified Navigation**: Clear, icon-based navigation with active states +- **Progress Indicators**: Loading states and progress feedback +- **Better Form Design**: Improved input styling with proper validation states +- **Interactive Elements**: Hover effects and smooth transitions +- **Card-Based Layout**: Organized content in digestible sections + +### ⚡ **Performance & Accessibility** +- **Semantic HTML**: Proper heading structure and ARIA labels +- **Keyboard Navigation**: Full keyboard accessibility +- **Color Contrast**: WCAG 2.1 AA compliant color combinations +- **Focus Management**: Clear focus indicators +- **Screen Reader Support**: Proper labeling and descriptions + +## New Components + +### Layout System +- **Layout.js**: Unified layout component with responsive sidebar +- **components.js**: Reusable UI components (Card, Button, Input, etc.) + +### Key Features + +#### 1. Unified Navigation +- Logo and branding in header +- Clear section navigation (Przekrój, Siatka, Uziomy) +- User authentication status +- Responsive mobile menu + +#### 2. Enhanced Cards +- Clean card design with headers and content sections +- Proper spacing and typography +- Action buttons with loading states +- Status indicators and badges + +#### 3. Improved Forms +- Better input styling with floating labels +- Proper validation states +- Radio groups and select inputs +- Date picker integration + +#### 4. Better Feedback +- Loading spinners for async operations +- Success/error alerts with proper styling +- Progress indicators +- Toast notifications + +## Technical Implementation + +### Dependencies Added +- `@heroicons/react`: Modern icon system +- `@tailwindcss/forms`: Enhanced form styling + +### File Structure +``` +components/ + ui/ + Layout.js # Main layout wrapper + components.js # Reusable UI components + templates/ + generator_new.js # Updated terrain profile generator + manual_new.js # Updated manual input component +pages/ + cross_new.js # Updated grid generator page + uziomy_new.js # Updated grounding calculator page +``` + +### Color System +- **Primary**: Blue (#3B82F6) for main actions +- **Secondary**: Gray tones for secondary elements +- **Success**: Green for positive states +- **Warning**: Yellow for attention states +- **Error**: Red for error states + +### Typography Scale +- **Headings**: Inter font with proper weight hierarchy +- **Body**: 14px base with good line height +- **Code**: Monospace for technical data input + +## Benefits + +### For Users +- **Easier Navigation**: Intuitive interface reduces learning curve +- **Better Mobile Experience**: Responsive design works on all devices +- **Faster Workflows**: Streamlined forms and clear action buttons +- **Professional Appearance**: Modern design builds trust and credibility + +### For Developers +- **Component Reusability**: Consistent design system +- **Maintainable Code**: Clean component architecture +- **Modern Stack**: Latest design practices and tools +- **Scalable System**: Easy to extend and modify + +## Implementation Notes + +### Backward Compatibility +- Original files preserved (can switch back if needed) +- New files use `_new.js` suffix for testing +- API endpoints remain unchanged +- All functionality preserved + +### Migration Path +1. Test new components in development +2. Gradually replace old components +3. Update remaining templates to match new design +4. Remove old components once migration complete + +### Browser Support +- Modern browsers (Chrome, Firefox, Safari, Edge) +- Mobile browsers (iOS Safari, Chrome Mobile) +- Progressive enhancement for older browsers + +This redesign transforms Wastpol into a modern, professional application that enhances user productivity while maintaining all existing engineering capabilities. diff --git a/archive/README.md b/archive/README.md new file mode 100644 index 0000000..90f0564 --- /dev/null +++ b/archive/README.md @@ -0,0 +1,39 @@ +# Archive - Old UI Components + +This folder contains the original versions of components and pages that were replaced during the UI redesign. + +## Archived Files + +### Pages +- `cross_old.js` - Original cross-section generator page +- `uziomy_old.js` - Original grounding calculator page + +### Components +- `templates/generator_old.js` - Original profile generator component +- `templates/manual_old.js` - Original manual input component + +## What Changed + +The archived files used the old UI system with: +- Evergreen UI components +- Older styling approach +- Less responsive design +- Basic user interface + +The new versions (now default) feature: +- Modern Tailwind CSS design system +- Responsive layout with sidebar navigation +- Custom UI components (`components/ui/`) +- Improved user experience +- Heroicons v2 integration +- Better mobile support + +## Restoration + +If you need to restore an old version, you can: +1. Copy the desired file from this archive +2. Rename it to remove the `_old` suffix +3. Replace the current version in the main project + +## Date Archived +Archived on: July 1, 2025 diff --git a/archive/components/templates/generator_old.js b/archive/components/templates/generator_old.js new file mode 100644 index 0000000..ac035a0 --- /dev/null +++ b/archive/components/templates/generator_old.js @@ -0,0 +1,231 @@ +import { useState, useEffect } from "react"; +import { useRouter } from "next/router"; +import { + Pane, + TextInputField, + TextareaField, + Button, + BuildIcon, + toaster, + Alert, + RadioGroup, +} from "evergreen-ui"; +import axios from "axios"; + +import Footer from "./footer"; + +export default function Generator() { + const [profil, setProfil] = useState(); + const [args, setArgs] = useState({ + scale: 200, + elementOne: 0, + elementTwo: 0, + }); + const [ElementOneOptions] = useState([ + { label: "Nic", value: "0" }, + { label: "Słup", value: "1" }, + { label: "Dom", value: "2" }, + ]); + const [ElementTwoOptions] = useState([ + { label: "Nic", value: "0" }, + { label: "Słup", value: "1" }, + { label: "Dom", value: "2" }, + ]); + const { query } = useRouter(); + + useEffect(() => { + if (query.external == "tru") { + axios + .post("/api/readtext", { + id: query.id, + }) + .then(function (response) { + setProfil(response.data.data); + document.getElementById("textarea-1").value = response.data.data; + console.log(response.data.data); + }); + } + }, []); + + const getPath = (e, path) => { + let newLines = []; + + for (let line of path.split("\n")) { + if (line[0] == "P") continue; + if (line[0] == "S") continue; + if (line[0] == "X") continue; + + newLines.push(line); + } + let xs = []; + let ys = []; + let zs = []; + let toti = 0; + let al = 0; + for (let line of newLines) { + al += 1; + let theLine = line.split(","); + //console.log(theLine) + if ( + xs && + parseFloat(theLine[0]) == xs[-1] && + parseFloat(theLine[1]) == ys[-1] + ) + continue; + + if (al > 2) { + let dist = + ((xs[xs.length - 1] - xs[xs.length - 2]) ** 2 + + (ys[ys.length - 1] - ys[ys.length - 2]) ** 2) ** + 0.5; + toti += Math.round(dist); + } + xs.push(parseFloat(theLine[0])); + ys.push(parseFloat(theLine[1])); + zs.push(parseFloat(theLine[2])); + } + let prevLine = ["0", "0", "0"]; + let scaleFactor = 100000 / 2000; + const canvas = document.getElementById("canvas"); + + if (!canvas.getContext) { + console.log("canvas err"); + toaster.warning("canvas err"); + return; + } + + const ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, 700, 700); + + // set line stroke and line width + ctx.strokeStyle = "red"; + ctx.lineWidth = 2; + let totalH = Math.max(...zs); + let minH = Math.min(...zs); + for (let line = 0; line < xs.length - 1; line++) { + let theLine = [xs[line], ys[line], zs[line]]; + let x = parseFloat(theLine[0]) - parseFloat(prevLine[0]); + let y = parseFloat(theLine[1]) - parseFloat(prevLine[1]); + let x1 = line * scaleFactor; + let y1 = zs[line]; + let x2 = (line + 1) * scaleFactor; + let y2 = zs[line + 1]; + //console.log(x1, y1, x2, y2); + let b0 = 0; + let b1 = 500; + let z1 = b0 + (b1 - b0) * ((y1 - totalH) / (minH - totalH)); + let z2 = b0 + (b1 - b0) * ((y2 - totalH) / (minH - totalH)); + + //b0 + (b1 - b0) * ((x1-0)/(toti*scaleFactor-0)); + let x12 = b0 + (b1 - b0) * ((x1 - 0) / (toti * scaleFactor)); + let x22 = b0 + (b1 - b0) * ((x2 - 0) / (toti * scaleFactor)); + //console.log(x12); + + ctx.beginPath(); + ctx.moveTo(x12, z1); + ctx.lineTo(x22, z2); + ctx.stroke(); + } + }; + + const parsePreview = (e) => { + // console.log(dxf); + }; + + const py = (e, profil, args) => { + e.preventDefault(); + + axios + .post("/api/spawn", { + profil: profil, + arguments: args, + }) + .then(function (response) { + console.log(response); + if (response.data.toString().startsWith("Py Error")) { + toaster.danger(response.data); + return; + } + toaster.warning(response.data.data); + document.getElementById("down").download = + response.data.filename.toString() + ".dxf"; + document.getElementById("down").click(); + }) + .catch(function (error) { + console.log(error); + }); + }; + return ( +
+
+ + { + //console.log(e.target.value); + setProfil(e.target.value); + parsePreview(e); + getPath(e, e.target.value); + }} + /> + + { + console.log(e.target.value); + setArgs({ ...args, scale: e.target.value }); + }} + /> + { + setArgs({ ...args, elementOne: event.target.value }); + }} + /> + { + setArgs({ ...args, elementTwo: event.target.value }); + }} + /> + + + + + {" "} + +
+ + + +
+ ); +} diff --git a/archive/components/templates/manual_old.js b/archive/components/templates/manual_old.js new file mode 100644 index 0000000..49f7c32 --- /dev/null +++ b/archive/components/templates/manual_old.js @@ -0,0 +1,157 @@ +import { useState, useEffect } from "react"; +import { + Pane, + TextInputField, + TextareaField, + Button, + toaster, + Alert, + TrashIcon, + Icon, +} from "evergreen-ui"; +import axios from "axios"; +import Footer from "./footer"; +import Generator from "./generator"; + +export default function Manual() { + const [points, setPoints] = useState([{ id: 0, len: 0, height: 0 }]); + const [args, setArgs] = useState({ scale: 200 }); + + //useEffect(() => { + //do something here + // }, [points]); + + const reIndex = () => { + let newId = 0; + let newPoints = []; + for (let point of points) { + point.id = newId; + newPoints.push(point); + newId += 1; + } + setPoints([...newPoints]); + }; + + const generation = (e) => { + let pointString = "Próbkowanie: 1\nSegment 0: w dół\nX: Y, Z"; + + for (let point of points) { + pointString += "\n"; + pointString += Number(point.len) * 1.0; + pointString += ", 1.0, "; + pointString += point.height; + } + + console.log(pointString); + py(e, pointString, args); + }; + + const py = (e, profil, args) => { + e.preventDefault(); + + axios + .post("/api/spawn", { + profil: profil, + arguments: args, + }) + .then(function (response) { + console.log(response); + if (response.data.toString().startsWith("Py Error")) { + toaster.danger(response.data); + return; + } + toaster.warning(response.data.data); + document.getElementById("down").download = + response.data.filename.toString() + ".dxf"; + document.getElementById("down").click(); + }) + .catch(function (error) { + console.log(error); + }); + }; + + return ( +
+
+ + {points.map((point, index) => ( + + { + console.log(e.target.value); + let newPoints = points; + newPoints[index].len = e.target.value; + setPoints([...newPoints]); + }} + value={point.len} + > + { + console.log(e.target.value); + let newPoints = points; + newPoints[index].height = e.target.value; + setPoints([...newPoints]); + }} + value={point.height} + onKeyDown={(e) => { + if (e.key == "Enter") { + setPoints([ + ...points, + { + id: points.length, + len: Number(points[points.length - 1].len) + 1, + height: 0, + }, + ]); + + let nextDiv = e.target.parentNode.parentNode.nextSibling; + nextDiv.childNodes[1].childNodes[1].focus() + nextDiv.childNodes[1].childNodes[1].setSelectionRange(0, 1) + } + }} + > + + + ))} + + + +
+
+ ); +} diff --git a/archive/pages/cross_old.js b/archive/pages/cross_old.js new file mode 100644 index 0000000..777aab5 --- /dev/null +++ b/archive/pages/cross_old.js @@ -0,0 +1,178 @@ +import { useState, useCallback } from "react"; +import { useSession, signIn } from "next-auth/react"; +import Layout from "../components/ui/Layout"; +import { Card, CardHeader, CardContent, CardTitle, CardDescription, Button, Alert } from "../components/ui/components"; +import { + FileUploader, + FileCard, +} from "evergreen-ui"; +import { CloudArrowUpIcon as CloudUploadIcon, ArrowDownTrayIcon as DownloadIcon, Squares2X2Icon as GridIcon } from '@heroicons/react/24/outline'; +import axios from "axios"; + +export default function Cross() { + const { data: session } = useSession(); + + const [fileData, setFileData] = useState(null); + const handleDownload = () => { + console.log("down"); + if (fileData) { + console.log("load"); + // const link = document.createElement("a"); + // link.href = `data:application/octet-stream;base64,${fileData}`; + // link.download = "plik.dxf"; + // link.click(); + document.getElementById("down").download = fileData.filename; + console.log(fileData.filename) + + document.getElementById("down").href = "cross.dxf"; + console.log("cross.dxf") + + document.getElementById("down").click(); + } + }; + + const [files, setFiles] = useState([]); + const [fileRejections, setFileRejections] = useState([]); + const handleChange = useCallback((files) => setFiles([files[0]]), []); + const handleRejected = useCallback( + (fileRejections) => setFileRejections([fileRejections[0]]), + [] + ); + const handleRemove = useCallback(() => { + setFiles([]); + setFileRejections([]); + }, []); + + const handleSubmit = async (event) => { + event.preventDefault(); + + let file = files[0]; + + if (!file) { + // Handle error if no file is selected + return; + } + + const formData = new FormData(); + formData.append("file", file); + + axios + .post("/api/upload", formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }) + .then((response) => { + console.log(response.data); + if (response.data.toString().startsWith("Py Error")) { + toaster.danger(response.data); + return; + } + toaster.warning(response.statusText); + console.log(response.data) + setFileData(response.data); + document.getElementById("download").disabled = false; + + // document.getElementById("down").download = + // response.data.filename.toString().split(".")[0].split("-")[1]+"_s.dxf"; + // document.getElementById("down").href = + // "uploads/"+response.data.filename.toString().split(".")[0]+"_s.dxf"; + // document.getElementById("down").click(); + }) + .catch((error) => { + console.error(error); + }); + }; + + if (session) { + return ( +
+ + Wastpol + + +
+
+ +
+ { + const { name, size, type } = file; + const fileRejection = fileRejections.find( + (fileRejection) => fileRejection.file === file + ); + const { message } = fileRejection || {}; + return ( + + ); + }} + values={files} + /> + + + + + {" "} + +
+
+ ); + } + return ( +
+ + Wastpol + +
+

Nie zalogowano

+

+ +
+
+ ); +} diff --git a/archive/pages/uziomy_old.js b/archive/pages/uziomy_old.js new file mode 100644 index 0000000..8fbebe1 --- /dev/null +++ b/archive/pages/uziomy_old.js @@ -0,0 +1,551 @@ +import Head from "next/head"; +import styles from "../styles/Home.module.css"; +import Nav from "../components/templates/nav"; +import UserTop from "../components/templates/userTop"; +import { useSession, signIn, signOut } from "next-auth/react"; +import { useState, useCallback } from "react"; +import { + Pane, + TextInputField, + TextareaField, + Button, + BuildIcon, + toaster, + Alert, + FileUploader, + FilePicker, + FileCard, + RadioGroup, + Autocomplete, +} from "evergreen-ui"; + +import PizZip from "pizzip"; +import Docxtemplater from "docxtemplater"; +import DatePicker from "react-datepicker"; +import { registerLocale, setDefaultLocale } from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; +import pl from "date-fns/locale/pl"; +registerLocale("pl", pl); + +export default function Rezy() { + const { data: session } = useSession(); + const [currentStep, setCurrentStep] = useState(1); + + const [ground, setGround] = useState({ + wet_coef: 0, + resistivity: 0, + resistance: 0, + measure_dist: 0, + rod_len: 0, + rod_num: 0, + rod_coef: 0, + hor_len: 0, + result_v: 0, + result_h: 0, + result: 0, + wszrg_h: 0, + wszrg_v: 0, + wanted: 0, + date: undefined, + no: 0, + pr_title: "Budowa przyłącza kablowego nN", + in_city: undefined, + commune: undefined, + all_parcels: undefined, + target_parcel: undefined, + geo_data: undefined, + object: "Przyłącz kablowy nN", + objValue1: "proj.", + objName: undefined, + }); + + // Function to go to the next step + const goToNextStep = () => { + if (currentStep < 3) { + setCurrentStep(currentStep + 1); + } + }; + + // Function to go to the previous step + const goToPreviousStep = () => { + if (currentStep > 1) { + setCurrentStep(currentStep - 1); + } + }; + + const [date, setDate] = useState(null); + const [calDate, setCalDate] = useState(null); + + const [options] = useState([ + { label: "5 Ω", value: "5" }, + { label: "10 Ω", value: "10" }, + { label: "15 Ω", value: "15" }, + { label: "30 Ω", value: "30" }, + ]); + const [neededValue, setNeededValue] = useState("5"); + + const [resHValue, setResHValue] = useState("88"); + const [resVValue, setResVValue] = useState("89"); + + const [objOptions1] = useState([ + { label: "proj.", value: "proj." }, + { label: "istn.", value: "istn." }, + ]); + const [objValue1, setObjValue1] = useState("proj."); + + function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + function parseDate(dateString) { + console.log(dateString); + const parts = dateString.split("."); + const day = parseInt(parts[0], 10); + const month = parseInt(parts[1], 10) - 1; // Months are 0-indexed in JavaScript Dates + const year = parseInt(parts[2], 10); + return new Date(year, month, day); + } + + function getGrounding(wanted, wszrg_h, wszrg_v, date) { + const dateObject = parseDate(date); + const month = dateObject.getMonth() + 1; // JavaScript months are 0-indexed + + const wet_coef = month >= 6 && month <= 9 ? 1.2 : 1.6; + const rod_len = wanted === 30 ? 2 : 3; + + const resistivity_h = wszrg_h / wet_coef; + const measure_dist_h = 1; + const resistance_h = resistivity_h / (2 * Math.PI * measure_dist_h); + + const resistivity_v = wszrg_v / wet_coef; + const measure_dist_v = 1 + rod_len; + const resistance_v = resistivity_v / (2 * Math.PI * measure_dist_v); + + const result_v = + (wszrg_v / (2 * Math.PI * rod_len)) * + (Math.log((8 * rod_len) / 0.016) - 1); + + let rod_num = 2; //minimum 2 rods + + let hor_len = 1 + (rod_num - 1) * rod_len * 2; + + let result_h = + (wszrg_h / (2 * Math.PI * hor_len)) * + Math.log((hor_len * hor_len) / (1 * 0.0191)); + + let rod_coef = + Math.pow(rod_num, 4) * 0.00002 - + Math.pow(rod_num, 3) * 0.0009 + + Math.pow(rod_num, 2) * 0.0137 - + rod_num * 0.0981 + + 1.0468; + + let result = + (result_v * result_h) / + (result_v * rod_coef + rod_num * result_h * rod_coef); + + while (result > wanted) { + rod_num += 1; + + hor_len = 1 + (rod_num - 1) * rod_len * 2; + + result_h = + (wszrg_h / (2 * Math.PI * hor_len)) * + Math.log((hor_len * hor_len) / (1 * 0.0191)); + + rod_coef = + Math.pow(rod_num, 4) * 0.00002 - + Math.pow(rod_num, 3) * 0.0009 + + Math.pow(rod_num, 2) * 0.0137 - + rod_num * 0.0981 + + 1.0468; + + result = + (result_v * result_h) / + (result_v * rod_coef + rod_num * result_h * rod_coef); + + console.log(result, rod_num); + } + + console.log(result, rod_num); + return { + wet_coef: wet_coef, + resistivity_h: resistivity_h.toFixed(2), + resistance_h: resistance_h.toFixed(2), + measure_dist_h: measure_dist_h, + resistivity_v: resistivity_v.toFixed(2), + resistance_v: resistance_v.toFixed(2), + measure_dist_v: measure_dist_v, + rod_len: rod_len, + rod_num: rod_num, + rod_coef: rod_coef.toFixed(2), + hor_len: hor_len, + result_v: result_v.toFixed(2), + result_h: result_h.toFixed(2), + result: result.toFixed(2), + wszrg_h: wszrg_h, + wszrg_v: wszrg_v, + wanted: neededValue, + }; + } + + const generateDocument = async (ground) => { + const data = { + ...ground, + resisted_object: ground.objValue1 + " " + ground.objName, + }; + + try { + const response = await fetch("/api/generateDocx", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error(`Error: ${response.status}`); + } + + // Convert the response to a blob and download it + const blob = await response.blob(); + const downloadUrl = window.URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = downloadUrl; + link.download = "opis.docx"; + document.body.appendChild(link); + link.click(); + link.remove(); + } catch (error) { + console.error("Failed to generate document:", error); + } + }; + + const generateDxf = async () => { + // Data that you want to send to the backend + var dateParts = ground.date.split("."); + + // Extract day, month, and year + var day = parseInt(dateParts[0], 10); + var month = parseInt(dateParts[1], 10); + var year = parseInt(dateParts[2], 10); + + // Format the result + var formattedDate = month.toString().padStart(2, "0") + "." + year; + const inputData = { + args: [ + ground.objValue1 + ground.objName, + ground.pr_title, + ground.object, + ground.in_city + + ", " + + ground.commune + + ", dz. nr " + + ground.all_parcels, + formattedDate, + ground.hor_len, + ground.rod_len, + ], + }; + // object1 = args[0] #ZK2a-1P + // object2 = args[1] #Budowa przyłącza + // object3 = args[2] #Przyłącze kablowe + // adres = args[3] + // date = args[4] + // len_h = int(args[5]) + // len_v = int(args[6]) + + try { + const response = await fetch("/api/generateDxf", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(inputData), + }); + + if (!response.ok) { + throw new Error("Response was not ok."); + } + + // Download the response (the output file) + const blob = await response.blob(); + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = downloadUrl; + a.download = "uziom.dxf"; + document.body.appendChild(a); + a.click(); + a.remove(); + } catch (error) { + console.error("There was an error:", error); + } + }; + + if (session) { + return ( +
+ + Wastpol + + +
+
+ +
+
+
+ 1. Data wykonania pomiaru +
+
+ + { + console.log(date); + console.log(typeof date); + const day = date.getDate().toString().padStart(2, "0"); // Add leading zero if necessary + const month = (date.getMonth() + 1) + .toString() + .padStart(2, "0"); // Month is 0-indexed, add 1 to get the correct month + const year = date.getFullYear(); + const formattedDate = `${day}.${month}.${year}`; + console.log(formattedDate); + setGround((current) => ({ + ...current, + date: formattedDate, + })); + setCalDate(date); + }} + placeholderText="Wybierz datę" + dateFormat="dd.MM.yyyy" + /> + +
+
+ { + setNeededValue(event.target.value); + }} + /> + { + setResHValue(e.target.value); + setResVValue((ground.wanted==30)? + getRandomInt( + parseInt(e.target.value) - 10, + parseInt(e.target.value) - 4 + ):getRandomInt( + parseInt(e.target.value) - 20, + parseInt(e.target.value) - 10 + ) + + ); + }} + value={resHValue} + /> + + setGround((current) => ({ ...current, no: e.target.value })) + } + value={ground.no} + />{" "} +
+
+ + setGround((current) => ({ + ...current, + pr_title: e.target.value, + })) + } + value={ground.pr_title} + /> + + setGround((current) => ({ + ...current, + object: e.target.value, + })) + } + value={ground.object} + /> + + setGround((current) => ({ + ...current, + in_city: e.target.value, + })) + } + value={ground.in_city} + /> + + setGround((current) => ({ + ...current, + commune: e.target.value, + })) + } + value={ground.commune} + /> + + setGround((current) => ({ + ...current, + all_parcels: e.target.value, + })) + } + value={ground.all_parcels} + /> + + setGround((current) => ({ + ...current, + target_parcel: e.target.value, + })) + } + value={ground.target_parcel} + /> + + setGround((current) => ({ + ...current, + geo_data: e.target.value, + })) + } + value={ground.geo_data} + />{" "} +
+
+ { + setObjValue1(event.target.value); + setGround((current) => ({ + ...current, + objValue1: event.target.value, + })); + }} + /> + + setGround((current) => ({ + ...current, + objName: e.target.value, + })) + } + value={ground.objName} + /> + + + + + +

+ Uziemienie poziome: {ground.result_h} Ω ({ground.wszrg_h}) +

+

+ Uziemienie pionowe: {ground.result_v} Ω ({ground.wszrg_v}) +

+

Uziemienie: {ground.result} Ω

+

Szpile: {ground.rod_num} szt

+

Bednarka: {ground.hor_len} m

+
+
+
+
+ ); + } + + return ( +
+ + Wastpol + +
+

Nie zalogowano

+

+ +
+
+ ); +} diff --git a/components/templates/generator.js b/components/templates/generator.js index ac035a0..e1b08ab 100644 --- a/components/templates/generator.js +++ b/components/templates/generator.js @@ -1,19 +1,9 @@ import { useState, useEffect } from "react"; import { useRouter } from "next/router"; -import { - Pane, - TextInputField, - TextareaField, - Button, - BuildIcon, - toaster, - Alert, - RadioGroup, -} from "evergreen-ui"; +import { Card, CardHeader, CardContent, CardTitle, CardDescription, Button, Input, Textarea, Alert } from "../ui/components"; +import { ChartBarIcon, ArrowDownTrayIcon as DownloadIcon, EyeIcon } from '@heroicons/react/24/outline'; import axios from "axios"; -import Footer from "./footer"; - export default function Generator() { const [profil, setProfil] = useState(); const [args, setArgs] = useState({ @@ -21,18 +11,22 @@ export default function Generator() { elementOne: 0, elementTwo: 0, }); - const [ElementOneOptions] = useState([ - { label: "Nic", value: "0" }, - { label: "Słup", value: "1" }, - { label: "Dom", value: "2" }, - ]); - const [ElementTwoOptions] = useState([ - { label: "Nic", value: "0" }, - { label: "Słup", value: "1" }, - { label: "Dom", value: "2" }, - ]); + const [isLoading, setIsLoading] = useState(false); + const [previewVisible, setPreviewVisible] = useState(false); const { query } = useRouter(); + const ElementOneOptions = [ + { label: "Nic", value: "0" }, + { label: "Słup", value: "1" }, + { label: "Dom", value: "2" }, + ]; + + const ElementTwoOptions = [ + { label: "Nic", value: "0" }, + { label: "Słup", value: "1" }, + { label: "Dom", value: "2" }, + ]; + useEffect(() => { if (query.external == "tru") { axios @@ -54,86 +48,68 @@ export default function Generator() { if (line[0] == "P") continue; if (line[0] == "S") continue; if (line[0] == "X") continue; - newLines.push(line); } - let xs = []; - let ys = []; - let zs = []; - let toti = 0; - let al = 0; + + let xs = [], ys = [], zs = []; + let toti = 0, al = 0; + for (let line of newLines) { al += 1; let theLine = line.split(","); - //console.log(theLine) - if ( - xs && - parseFloat(theLine[0]) == xs[-1] && - parseFloat(theLine[1]) == ys[-1] - ) + + if (xs && parseFloat(theLine[0]) == xs[-1] && parseFloat(theLine[1]) == ys[-1]) continue; if (al > 2) { - let dist = - ((xs[xs.length - 1] - xs[xs.length - 2]) ** 2 + - (ys[ys.length - 1] - ys[ys.length - 2]) ** 2) ** - 0.5; + let dist = ((xs[xs.length - 1] - xs[xs.length - 2]) ** 2 + + (ys[ys.length - 1] - ys[ys.length - 2]) ** 2) ** 0.5; toti += Math.round(dist); } xs.push(parseFloat(theLine[0])); ys.push(parseFloat(theLine[1])); zs.push(parseFloat(theLine[2])); } - let prevLine = ["0", "0", "0"]; - let scaleFactor = 100000 / 2000; - const canvas = document.getElementById("canvas"); + const canvas = document.getElementById("canvas"); if (!canvas.getContext) { console.log("canvas err"); - toaster.warning("canvas err"); return; } const ctx = canvas.getContext("2d"); - ctx.clearRect(0, 0, 700, 700); - - // set line stroke and line width - ctx.strokeStyle = "red"; + ctx.clearRect(0, 0, 700, 500); + ctx.strokeStyle = "#3B82F6"; ctx.lineWidth = 2; + + let scaleFactor = 100000 / 2000; let totalH = Math.max(...zs); let minH = Math.min(...zs); + for (let line = 0; line < xs.length - 1; line++) { - let theLine = [xs[line], ys[line], zs[line]]; - let x = parseFloat(theLine[0]) - parseFloat(prevLine[0]); - let y = parseFloat(theLine[1]) - parseFloat(prevLine[1]); let x1 = line * scaleFactor; let y1 = zs[line]; let x2 = (line + 1) * scaleFactor; let y2 = zs[line + 1]; - //console.log(x1, y1, x2, y2); - let b0 = 0; - let b1 = 500; + + let b0 = 50, b1 = 450; let z1 = b0 + (b1 - b0) * ((y1 - totalH) / (minH - totalH)); let z2 = b0 + (b1 - b0) * ((y2 - totalH) / (minH - totalH)); - - //b0 + (b1 - b0) * ((x1-0)/(toti*scaleFactor-0)); + let x12 = b0 + (b1 - b0) * ((x1 - 0) / (toti * scaleFactor)); let x22 = b0 + (b1 - b0) * ((x2 - 0) / (toti * scaleFactor)); - //console.log(x12); ctx.beginPath(); ctx.moveTo(x12, z1); ctx.lineTo(x22, z2); ctx.stroke(); } - }; - - const parsePreview = (e) => { - // console.log(dxf); + setPreviewVisible(true); }; const py = (e, profil, args) => { e.preventDefault(); + setIsLoading(true); axios .post("/api/spawn", { @@ -141,91 +117,178 @@ export default function Generator() { arguments: args, }) .then(function (response) { + setIsLoading(false); console.log(response); if (response.data.toString().startsWith("Py Error")) { - toaster.danger(response.data); + alert("Błąd: " + response.data); return; } - toaster.warning(response.data.data); - document.getElementById("down").download = - response.data.filename.toString() + ".dxf"; + document.getElementById("down").download = response.data.filename.toString() + ".dxf"; document.getElementById("down").click(); }) .catch(function (error) { + setIsLoading(false); console.log(error); }); }; + return ( -
-
- - { - //console.log(e.target.value); - setProfil(e.target.value); - parsePreview(e); - getPath(e, e.target.value); - }} - /> +
+ {/* Input Section */} +
+ + + + + Dane wejściowe + + + Wklej dane z Geoportalu lub wprowadź własne współrzędne + + + +