diff --git a/.gitignore b/.gitignore index 272b464..3bb2f3d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ frontend/.vite node_modules pestgres_data/ redis_data/ +frontend-rewrite aisugestions.md diff --git a/backend/src/config/cors.config.ts b/backend/src/config/cors.config.ts index 3778439..98c9fbc 100644 --- a/backend/src/config/cors.config.ts +++ b/backend/src/config/cors.config.ts @@ -1,6 +1,8 @@ export const corsConfig = { origin: [ "http://localhost:5173", + "http://localhost:4444", + "http://localhost:3000", "https://www.placebo.mk", "https://placebo.mk", "https://imkapi.oblak.solutions", diff --git a/backend/src/email/email.service.ts b/backend/src/email/email.service.ts index a5b4256..5aa6383 100644 --- a/backend/src/email/email.service.ts +++ b/backend/src/email/email.service.ts @@ -227,8 +227,9 @@ export class EmailService { async sendPasswordResetEmail(email: string, name: string, token: string) { this.logger.log("Sending password reset email to:", email); - - const resetLink = `${process.env.FRONTEND_URL}/reset-password?token=${token}`; + const frontendUrl = + this.configService.get("FRONTEND_URL") || "https://placebo.mk"; + const resetLink = `${frontendUrl}/reset-password?token=${token}`; const mailOptions = { from: this.from, to: email, diff --git a/docker-reset.md b/docker-reset.md index 7e42cd6..c953f83 100644 --- a/docker-reset.md +++ b/docker-reset.md @@ -1,31 +1,35 @@ # Stop everything + docker-compose down # Remove all containers + docker rm -f $(docker ps -a -q) # Remove all volumes + docker volume rm $(docker volume ls -q) # Remove all images + docker rmi -f $(docker images -q) # Start fresh + docker-compose up --build - - # reset development + # Stop containers and remove volumes + docker-compose -f docker-compose.dev.yml down -v # Remove existing images + docker rmi $(docker images -q backend_backend) # Rebuild and start + docker-compose -f docker-compose.dev.yml up --build - - - docker-compose -f docker-compose.dev.yml up --build --force-recreate diff --git a/frontend/public/Sertifikat za akreditacija IMK.png b/frontend/public/Sertifikat za akreditacija IMK.png new file mode 100644 index 0000000..1248b73 Binary files /dev/null and b/frontend/public/Sertifikat za akreditacija IMK.png differ diff --git a/frontend/public/resenie_imk.png b/frontend/public/resenie_imk.png new file mode 100644 index 0000000..7079994 Binary files /dev/null and b/frontend/public/resenie_imk.png differ diff --git a/frontend/src/components/Certificates/Certificates.jsx b/frontend/src/components/Certificates/Certificates.jsx index a8da7a6..2dad488 100644 --- a/frontend/src/components/Certificates/Certificates.jsx +++ b/frontend/src/components/Certificates/Certificates.jsx @@ -1,103 +1,161 @@ -import { useEffect } from 'react'; -import { motion } from 'framer-motion'; -import { Card } from '../UI/Card'; -import { ScrollDownArrow } from '../UI/ScrollDownArrow'; +import { useEffect, useState } from "react"; +import { motion } from "framer-motion"; +import { Card } from "../UI/Card"; +import { ScrollDownArrow } from "../UI/ScrollDownArrow"; export default function Certificates() { - useEffect(() => { - // Ensure the scroll happens after the component is fully mounted - const timer = setTimeout(() => { - window.scrollTo({ - top: 0, - behavior: "smooth" - }); - }, 100); + useEffect(() => { + // Ensure the scroll happens after the component is fully mounted + const timer = setTimeout(() => { + window.scrollTo({ + top: 0, + behavior: "smooth", + }); + }, 100); - return () => clearTimeout(timer); - }, []); + return () => clearTimeout(timer); + }, []); - const certificates = [ - { - id: 1, - image: "/sertifikat1.jpg", - alt: "Сертификат за акредитација", - title: "Сертификат за акредитација", - description: "Официјален сертификат за акредитација на нашата лабораторија" - }, - { - id: 2, - image: "/sertifikat2.jpg", - alt: "Сертификат за квалитет", - title: "Сертификат за квалитет", - description: "Потврда за нашиот систем за управување со квалитет" - } - ]; + const [selectedCertificate, setSelectedCertificate] = useState(null); + const certificates = [ + { + id: 1, + image: "/sertifikat1.jpg", + alt: "Сертификат за акредитација", + title: "Сертификат за акредитација", + description: + "Официјален сертификат за акредитација на нашата лабораторија", + }, + { + id: 2, + image: "/sertifikat2.jpg", + alt: "Сертификат за квалитет", + title: "Сертификат за квалитет", + description: "Потврда за нашиот систем за управување со квалитет", + }, + { + id: 3, + image: "/resenie_imk.png", + alt: "resenie ", + title: "resenie", + description: "some description", + }, + { + id: 4, + alt: "Сертификат", + image: "/Sertifikat za akreditacija IMK.png", + title: "Сертификат за акредитација", + description: "Официјален сертификат за акредитација", + }, + ]; - return ( -
- {/* Hero Section */} -
-
-
-
- -

- Сертификати и Акредитации -

-
-

- Нашата посветеност кон квалитет и професионалност е потврдена со меѓународно признати сертификати -

-
+ const handleCertificateClick = (certificate) => { + setSelectedCertificate(certificate); + }; - -
-
-
+ const closeModal = () => { + setSelectedCertificate(null); + }; + return ( +
+ {/* Hero Section */} +
+
+
+
+ +

+ Сертификати и Акредитации +

+
+

+ Нашата посветеност кон квалитет и професионалност е потврдена со + меѓународно признати сертификати +

+
- {/* Certificates Section */} -
-
-
- {certificates.map((certificate, index) => ( - - - - {certificate.alt} - -
-

- {certificate.title} -

-

- {certificate.description} -

-
-
-
- ))} -
-
-
+ +
- ); -} \ No newline at end of file +
+ + {/* Certificates Section */} +
+
+
+ {certificates.map((certificate, index) => ( + handleCertificateClick(certificate)} + className="cursor-pointer" + > + + + {certificate.alt} + +
+

+ {certificate.title} +

+

+ {certificate.description} +

+
+
+
+ ))} +
+
+
+ + {selectedCertificate && ( +
+ {/*
*/} + {/* */} +
+ + {/*

*/} + {/* {selectedCertificate.title} */} + {/*

*/} + {/*

*/} + {/* {selectedCertificate.description} */} + {/*

*/} +
+
+ )} +
+ ); +} + diff --git a/frontend/src/components/UI/ScrollDownArrow.jsx b/frontend/src/components/UI/ScrollDownArrow.jsx index 593a936..10c2c4c 100644 --- a/frontend/src/components/UI/ScrollDownArrow.jsx +++ b/frontend/src/components/UI/ScrollDownArrow.jsx @@ -1,41 +1,42 @@ -import { motion } from 'framer-motion'; +import { motion } from "framer-motion"; -export function ScrollDownArrow({ targetId = 'content' }) { - const scrollToContent = () => { - const contentSection = document.getElementById(targetId); - contentSection?.scrollIntoView({ behavior: 'smooth' }); - }; +export function ScrollDownArrow({ targetId = "content" }) { + const scrollToContent = () => { + const contentSection = document.getElementById(targetId); + contentSection?.scrollIntoView({ behavior: "smooth" }); + }; + + return ( + + + + + + ); +} - return ( - - - - - - ); -} \ No newline at end of file diff --git a/frontend/src/components/login/Login.jsx b/frontend/src/components/login/Login.jsx index 20ae9f7..8bc2d6c 100644 --- a/frontend/src/components/login/Login.jsx +++ b/frontend/src/components/login/Login.jsx @@ -48,11 +48,9 @@ export default function Login() { >

- Sign in to your account + Логирај се на својот акаунт

-

- Welcome back! Please enter your details. -

+

Добредојдовте!

{error && ( @@ -64,19 +62,19 @@ export default function Login() {
setFormData({ ...formData, username: e.target.value }) } error={error} - className="bg-neutral-800/50 border-neutral-700 text-white placeholder-neutral-400 + className="p-2 bg-neutral-800/50 border-neutral-700 text-white placeholder-neutral-400 focus:border-primary-400 focus:ring-primary-400" /> @@ -84,7 +82,7 @@ export default function Login() {
{/*
diff --git a/frontend/src/components/navbar/Navbar.jsx b/frontend/src/components/navbar/Navbar.jsx index 02fbcca..29ec91f 100644 --- a/frontend/src/components/navbar/Navbar.jsx +++ b/frontend/src/components/navbar/Navbar.jsx @@ -54,7 +54,7 @@ export default function Navbar() {
{/* Left Logo */}
- + Одјави се
)} - {/* TUF Logo */} -
- - TUF logo - -
+ {/*
*/} + {/* */} + {/* TUF logo */} + {/* */} + {/*
*/} {/* Mobile Menu Button */}
-
-
-
- - +
@@ -224,5 +232,6 @@ export default function Contact() {
- ) -} \ No newline at end of file + ); +} + diff --git a/frontend/src/pages/homepage/Home.jsx b/frontend/src/pages/homepage/Home.jsx index e4adca0..db64284 100644 --- a/frontend/src/pages/homepage/Home.jsx +++ b/frontend/src/pages/homepage/Home.jsx @@ -2,7 +2,7 @@ import { Link } from "react-router-dom"; import { motion } from "framer-motion"; import { ArrowRightIcon, CheckCircleIcon } from "@heroicons/react/24/outline"; import { Button, Card } from "../../components/UI"; -import { ScrollDownArrow } from '../../components/UI/ScrollDownArrow'; +import { ScrollDownArrow } from "../../components/UI/ScrollDownArrow"; const serviceCards = [ { @@ -109,7 +109,7 @@ export default function Home() { {/* Services Section */}
-
+

Нашите Услуги

@@ -121,11 +121,7 @@ export default function Home() {
{serviceCards.map((card) => ( - + {card.description}

    {card.services.slice(0, 3).map((service, index) => ( -
  • +
  • {service}
  • @@ -162,9 +161,6 @@ export default function Home() {
- - ); } - diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js index 68a704d..cc49aa9 100644 --- a/frontend/src/services/api.js +++ b/frontend/src/services/api.js @@ -1,7 +1,7 @@ import axios from "axios"; // const API_URL = "https://imkapi.oblak.solutions:3000"; -const API_URL = "https://localhost:3000"; +const API_URL = "http://localhost:3000"; const api = axios.create({ baseURL: API_URL, withCredentials: true,