From 06ffc05e2bd7ef172cca59b812082f0900dd1387 Mon Sep 17 00:00:00 2001 From: dimitar Date: Tue, 24 Jun 2025 21:36:56 +0200 Subject: [PATCH] backup --- backend/imk-backend/.env | 5 +- backend/imk-backend/prisma/seed.js | 82 ++++++ .../imk-backend/src/client/client.service.ts | 2 +- .../src/documents/documents.controller.ts | 30 ++- frontend/imk/package-lock.json | 21 ++ frontend/imk/package.json | 2 + frontend/imk/src/pages/aboutpage/About.jsx | 247 +++++++----------- frontend/imk/src/pages/homepage/Home.jsx | 30 ++- frontend/imk/src/services/xxFileUpload.jsx | 24 +- 9 files changed, 257 insertions(+), 186 deletions(-) create mode 100644 backend/imk-backend/prisma/seed.js diff --git a/backend/imk-backend/.env b/backend/imk-backend/.env index 3c6176e..eaff313 100644 --- a/backend/imk-backend/.env +++ b/backend/imk-backend/.env @@ -4,10 +4,11 @@ # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings -DATABASE_URL="postgresql://root:admin@localhost:5432/imk?schema=public" +DATABASE_URL="postgresql://root:irina76@localhost:5432/imk?schema=public" JWT_SECRET=some-secret AWS_REGION=EU2 AWS_ACCESS_KEY_ID=4d2f5655369a02100375e3247d7e1fe6 AWS_SECRET_ACCESS_KEY=6d4723e14c0d799b89948c24dbe983e4 AWS_S3_BUCKET_NAME=imk-data -AWS_ENDPOINT_URL=https://eu2.contabostorage.com \ No newline at end of file +AWS_ENDPOINT_URL=https://eu2.contabostorage.com + diff --git a/backend/imk-backend/prisma/seed.js b/backend/imk-backend/prisma/seed.js new file mode 100644 index 0000000..8a9e146 --- /dev/null +++ b/backend/imk-backend/prisma/seed.js @@ -0,0 +1,82 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var client_1 = require("@prisma/client"); +var bcrypt = require("bcrypt"); +var prisma = new client_1.PrismaClient(); +function main() { + return __awaiter(this, void 0, void 0, function () { + var hashedPassword, admin; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, bcrypt.hash('admin123', 10)]; + case 1: + hashedPassword = _a.sent(); + return [4 /*yield*/, prisma.user.upsert({ + where: { email: 'admin@example.com' }, + update: {}, + create: { + email: 'admin@example.com', + name: 'Admin User', + password: hashedPassword, + isAdmin: true, + }, + })]; + case 2: + admin = _a.sent(); + console.log({ admin: admin }); + return [2 /*return*/]; + } + }); + }); +} +main() + .catch(function (e) { + console.error(e); + process.exit(1); +}) + .finally(function () { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, prisma.$disconnect()]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); +}); }); diff --git a/backend/imk-backend/src/client/client.service.ts b/backend/imk-backend/src/client/client.service.ts index 62e1c1e..66adcca 100644 --- a/backend/imk-backend/src/client/client.service.ts +++ b/backend/imk-backend/src/client/client.service.ts @@ -19,7 +19,7 @@ export class ClientService { some: { id: Number(userId), }, - }, + }, }, include: { sharedWith: { diff --git a/backend/imk-backend/src/documents/documents.controller.ts b/backend/imk-backend/src/documents/documents.controller.ts index 3895f25..29db3ac 100644 --- a/backend/imk-backend/src/documents/documents.controller.ts +++ b/backend/imk-backend/src/documents/documents.controller.ts @@ -1,4 +1,13 @@ -import { Controller, Get, Param, Req, Res, UseGuards, Logger, Request } from '@nestjs/common'; +import { + Controller, + Get, + Param, + Req, + Res, + UseGuards, + Logger, + Request, +} from '@nestjs/common'; import { Response } from 'express'; import { DocumentsService } from './documents.service'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; @@ -17,7 +26,7 @@ export class DocumentsController { constructor( private readonly documentsService: DocumentsService, - private readonly s3Service: S3Service + private readonly s3Service: S3Service, ) {} @Get('shared/:userId') @@ -31,17 +40,18 @@ export class DocumentsController { async downloadDocument( @Param('key') key: string, @Request() req, - @Res() res: Response + @Res() res: Response, ) { try { this.logger.debug(`Download request for key: ${key}`); - + const decodedKey = decodeURIComponent(key); this.logger.debug(`Decoded key: ${decodedKey}`); // Get document from database first to verify access - const document = await this.documentsService.findDocumentByS3Key(decodedKey); - + const document = + await this.documentsService.findDocumentByS3Key(decodedKey); + if (!document) { return res.status(404).json({ message: 'Document not found' }); } @@ -49,7 +59,7 @@ export class DocumentsController { // Verify user has access to this document const hasAccess = await this.documentsService.verifyDocumentAccess( document.id, - req.user.id + req.user.id, ); if (!hasAccess) { @@ -58,7 +68,7 @@ export class DocumentsController { // Get the file from S3 const file = await this.s3Service.getFile(decodedKey); - + if (!file || !file.buffer) { return res.status(404).json({ message: 'File not found in storage' }); } @@ -72,9 +82,9 @@ export class DocumentsController { return res.send(file.buffer); } catch (error) { this.logger.error('Download error:', error); - return res.status(500).json({ + return res.status(500).json({ message: 'Failed to download file', - error: error.message + error: error.message, }); } } diff --git a/frontend/imk/package-lock.json b/frontend/imk/package-lock.json index 4487d37..87ddc2d 100644 --- a/frontend/imk/package-lock.json +++ b/frontend/imk/package-lock.json @@ -11,10 +11,12 @@ "@headlessui/react": "^1.7.17", "@heroicons/react": "^2.0.18", "axios": "^1.7.7", + "date-fns": "^4.1.0", "framer-motion": "^11.11.10", "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^5.5.0", "react-router-dom": "^6.15.0" }, "devDependencies": { @@ -1453,6 +1455,16 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "dev": true }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -3603,6 +3615,15 @@ "react": "^18.2.0" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/frontend/imk/package.json b/frontend/imk/package.json index 0191693..33661cf 100644 --- a/frontend/imk/package.json +++ b/frontend/imk/package.json @@ -13,10 +13,12 @@ "@headlessui/react": "^1.7.17", "@heroicons/react": "^2.0.18", "axios": "^1.7.7", + "date-fns": "^4.1.0", "framer-motion": "^11.11.10", "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^5.5.0", "react-router-dom": "^6.15.0" }, "devDependencies": { diff --git a/frontend/imk/src/pages/aboutpage/About.jsx b/frontend/imk/src/pages/aboutpage/About.jsx index 74e8c55..9fda718 100644 --- a/frontend/imk/src/pages/aboutpage/About.jsx +++ b/frontend/imk/src/pages/aboutpage/About.jsx @@ -1,180 +1,131 @@ -import { SectionHeader } from '../../shared/SectionHeader'; -import { Button } from '../../shared/Button'; -import { FiUsers, FiAward, FiCheckCircle, FiTrendingUp } from 'react-icons/fi'; +import { NavLink } from "react-router-dom"; +import { motion } from "framer-motion"; +import { SectionHeader } from "../../shared/SectionHeader"; +import { FiTrendingUp, FiAward, FiCheckCircle } from "react-icons/fi"; + +const milestones = [ + { year: "2008", title: "Основање на компанијата" }, + { year: "2012", title: "Проширување на лабораторијата" }, + { year: "2015", title: "ISO сертификација" }, + { year: "2018", title: "Воведување на нови услуги" }, + { year: "2020", title: "Модернизација на опремата" }, + { year: "2023", title: "Проширување на тимот" }, +]; export default function About() { - const stats = [ - { label: 'Години искуство', value: '15+' }, - { label: 'Задоволни клиенти', value: '500+' }, - { label: 'Завршени проекти', value: '1000+' }, - { label: 'Експерти во тимот', value: '20+' } - ]; - - const milestones = [ - { year: '2008', title: 'Основање на компанијата' }, - { year: '2012', title: 'Проширување на лабораторијата' }, - { year: '2015', title: 'ISO сертификација' }, - { year: '2018', title: 'Воведување на нови услуги' }, - { year: '2020', title: 'Модернизација на опремата' }, - { year: '2023', title: 'Проширување на тимот' } - ]; - return ( -
+
{/* Hero Section */} -
+
- Laboratory equipment
-
-

+ За Нас -

-

+ + Повеќе од 15 години искуство во обезбедување квалитет -

+
- {/* Stats Section */} - {/*
-
- {stats.map((stat, index) => ( -
-
{stat.value}
-
{stat.label}
-
- ))} -
-
*/} - {/* Vision & Values Section */} -
- - -
-
-
- -

- Визија -

-
-

- Нашата визија е да бидеме водечка компанија во областа на испитување на материјали и контрола на квалитет во Македонија. Стремиме кон постојано унапредување на нашите услуги преку имплементација на најсовремени технологии и методологии. Сакаме да воспоставиме нови стандарди во индустријата и да допринесеме за развојот на градежништвото и инженерството во регионот. -

-
- -
-
- -

- Вредности -

-
-
    -
  • - -
    - Квалитет - Посветени сме на обезбедување највисок квалитет во сите наши услуги -
    -
  • -
  • - -
    - Интегритет - Работиме со целосна транспарентност и професионална етика -
    -
  • -
  • - -
    - Иновација - Постојано инвестираме во нови технологии и методи -
    -
  • -
  • - -
    - Експертиза - Нашиот тим се состои од високо квалификувани професионалци -
    -
  • -
  • - -
    - Одговорност - Преземаме целосна одговорност за квалитетот на нашата работа -
    -
  • -
-
-
- - {/* Timeline Section */} -
- +
+ -
-
-
- {milestones.map((milestone, index) => ( -
-
-
-
{milestone.year}
-
{milestone.title}
-
-
-
- ))} -
-
-
- - {/* Team Section */} -
- -
- {[1, 2, 3].map((member) => ( -
-
- -
-

Име Презиме

-

Позиција

+
+
+
+ +

Визија

- ))} +

+ Нашата визија е да бидеме водечка компанија во областа на + испитување на материјали и контрола на квалитет во Македонија. + Стремиме кон постојано унапредување на нашите услуги преку + имплементација на најсовремени технологии и методологии. Сакаме + да воспоставиме нови стандарди во индустријата и да допринесеме + за развојот на градежништвото и инженерството во регионот. +

+
+
+
+ +

Вредности

+
+
    +
  • + +
    + Квалитет - Посветени + сме на обезбедување највисок квалитет во сите наши услуги +
    +
  • +
  • + +
    + Интегритет - + Работиме со целосна транспарентност и професионална етика +
    +
  • +
  • + +
    + Иновација - + Постојано инвестираме во нови технологии и методи +
    +
  • +
  • + +
    + Експертиза - Нашиот + тим се состои од високо квалификувани професионалци +
    +
  • +
  • + +
    + Одговорност - + Преземаме целосна одговорност за квалитетот на нашата работа +
    +
  • +
+
{/* CTA Section */} -
+
-

+

Започнете го вашиот проект со нас

- +
); -} \ No newline at end of file +} diff --git a/frontend/imk/src/pages/homepage/Home.jsx b/frontend/imk/src/pages/homepage/Home.jsx index fc736fe..7d71a83 100644 --- a/frontend/imk/src/pages/homepage/Home.jsx +++ b/frontend/imk/src/pages/homepage/Home.jsx @@ -5,7 +5,8 @@ import { SectionHeader } from "../../shared/SectionHeader"; const serviceCards = [ { title: "Лабораториски услуги", - description: "Професионални лабораториски испитувања со најсовремена опрема", + description: + "Професионални лабораториски испитувања со најсовремена опрема", image: "labfinal.webp", link: "/lab", services: [ @@ -13,8 +14,8 @@ const serviceCards = [ "Геотехнички испитувања", "Испитување на челик", "Испитување на руди, метали и троски", - "Лабораториска екстракција од руди и троски" - ] + "Лабораториска екстракција од руди и троски", + ], }, { title: "Ултразвучни испитувања", @@ -26,8 +27,8 @@ const serviceCards = [ "Дебелометрија", "Испитување на дефекти", "Контрола на квалитет", - "Анализа и известување" - ] + "Анализа и известување", + ], }, { title: "Консалтинг услуги", @@ -39,18 +40,17 @@ const serviceCards = [ "Проектен менаџмент", "Надзор на градба", "Техничка документација", - "Анализа на материјали" - ] - } + "Анализа на материјали", + ], + }, ]; export default function Home() { return (
{/* Hero Section with Parallax */} -
+
-
@@ -69,7 +69,8 @@ export default function Home() { transition={{ delay: 0.2 }} className="text-xl text-gray-200 mb-8" > - Професионални лабораториски услуги со најсовремена опрема и експертиза + Професионални лабораториски услуги со најсовремена опрема и + експертиза Дознајте повеќе @@ -124,7 +125,7 @@ export default function Home() { title="Нашите Услуги" subtitle="Нашиот тим е спремен да ви помогне со нашите услуги" className="text-white" - /> + />
{serviceCards.map((card) => (
); -} \ No newline at end of file +} + diff --git a/frontend/imk/src/services/xxFileUpload.jsx b/frontend/imk/src/services/xxFileUpload.jsx index cad41df..e19e88b 100644 --- a/frontend/imk/src/services/xxFileUpload.jsx +++ b/frontend/imk/src/services/xxFileUpload.jsx @@ -1,5 +1,5 @@ -import { useState } from 'react'; -import axios from 'axios'; +import { useState } from "react"; +import axios from "axios"; const FileUpload = () => { const [file, setFile] = useState(null); @@ -16,25 +16,26 @@ const FileUpload = () => { if (!file) return; const formData = new FormData(); - formData.append('file', file); - formData.append('title', 'Your document title'); - // Add other fields as needed + formData.append("file", file); + formData.append("title", "Your document title"); try { - await axios.post('/api/admin/document', formData, { + await axios.post("/api/admin/document", formData, { headers: { - 'Content-Type': 'multipart/form-data', + "Content-Type": "multipart/form-data", }, onUploadProgress: (progressEvent) => { - const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total); + const percentCompleted = Math.round( + (progressEvent.loaded * 100) / progressEvent.total, + ); setProgress(percentCompleted); }, }); - console.log('Upload successful'); + console.log("Upload successful"); setProgress(0); } catch (error) { - console.error('Upload failed:', error); + console.error("Upload failed:", error); setProgress(0); } }; @@ -53,4 +54,5 @@ const FileUpload = () => { ); }; -export default FileUpload; \ No newline at end of file +export default FileUpload; +