frontend redesign, implementing tailwind accross app, added shared component

This commit is contained in:
Dimitar765 2024-10-29 12:30:33 +01:00
parent 1a7f2afd79
commit ce893a4185
15 changed files with 1030 additions and 570 deletions

View File

@ -126,12 +126,36 @@ export class AdminService {
});
}
async createUser(createUserDto: CreateUserDto) {
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
// async createUser(createUserDto: CreateUserDto) {
// const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
// return this.prisma.user.create({
// data: {
// ...createUserDto,
// password: hashedPassword,
// },
// });
// }
async createUser(userData: {
name: string;
email: string;
password: string;
isAdmin: boolean;
}) {
const hashedPassword = await bcrypt.hash(userData.password, 10);
return this.prisma.user.create({
data: {
...createUserDto,
name: userData.name,
email: userData.email,
password: hashedPassword,
isAdmin: userData.isAdmin,
},
select: {
id: true,
name: true,
email: true,
isAdmin: true,
},
});
}

View File

@ -1,4 +1,4 @@
import { IsString, IsEmail, MinLength } from 'class-validator';
import { IsString, IsEmail, MinLength, IsBoolean } from 'class-validator';
export class CreateUserDto {
@IsString()
@ -10,4 +10,7 @@ export class CreateUserDto {
@IsString()
@MinLength(6)
password: string;
@IsBoolean()
isAdmin: boolean = false;
}

98
frontend/colorScheme Normal file
View File

@ -0,0 +1,98 @@
##color scheme across all components based on the Home page design.
--
We can create a colors file to maintain consistency
color.js
export const colors = {
primary: {
light: '#3B82F6', // blue-500
DEFAULT: '#2563EB', // blue-600
dark: '#1D4ED8', // blue-700
darker: '#1E40AF' // blue-800
},
background: {
light: '#F9FAFB', // gray-50
DEFAULT: '#F3F4F6', // gray-100
dark: '#E5E7EB' // gray-200
},
text: {
primary: '#1F2937', // gray-800
secondary: '#4B5563', // gray-600
light: '#9CA3AF' // gray-400
},
white: '#FFFFFF',
black: '#000000'
}
--
--
common component style
common.js
export const commonStyles = {
// Container
container: "container mx-auto px-4",
// Section Headers
sectionHeader: "text-center mb-16",
sectionTitle: "text-3xl md:text-4xl font-bold text-gray-800 mb-4",
sectionDivider: "w-24 h-1 bg-blue-600 mx-auto",
// Cards
card: "bg-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300",
// Buttons
primaryButton: "bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300",
secondaryButton: "bg-white/10 hover:bg-white/20 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300",
// Gradients
primaryGradient: "bg-gradient-to-r from-blue-900/90 to-blue-600/80",
// Text
heading1: "text-4xl md:text-6xl font-bold",
heading2: "text-3xl md:text-4xl font-bold",
heading3: "text-2xl font-semibold",
paragraph: "text-gray-600"
}
--
--
reusable section header component
SectionHeader.jsx
// Reusable section header component
export function SectionHeader({ title, subtitle }) {
return (
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-800 mb-4">
{title}
</h2>
<div className="w-24 h-1 bg-blue-600 mx-auto mb-8"></div>
{subtitle && (
<p className="text-gray-600 max-w-2xl mx-auto">
{subtitle}
</p>
)}
</div>
);
}
--
reusable button component
// Reusable button component
export function Button({ variant = 'primary', children, ...props }) {
const baseStyles = "px-8 py-3 rounded-full font-semibold transition-colors duration-300";
const variants = {
primary: "bg-blue-600 hover:bg-blue-700 text-white",
secondary: "bg-white/10 hover:bg-white/20 text-white",
outline: "border-2 border-blue-600 text-blue-600 hover:bg-blue-50"
};
return (
<button
className={`${baseStyles} ${variants[variant]}`}
{...props}
>
{children}
</button>
);
}
--

View File

@ -11,6 +11,7 @@
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"axios": "^1.7.7",
"framer-motion": "^11.11.10",
"jwt-decode": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@ -2160,6 +2161,30 @@
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/framer-motion": {
"version": "11.11.10",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.10.tgz",
"integrity": "sha512-061Bt1jL/vIm+diYIiA4dP/Yld7vD47ROextS7ESBW5hr4wQFhxB5D5T5zAc3c/5me3cOa+iO5LqhA38WDln/A==",
"dependencies": {
"tslib": "^2.4.0"
},
"peerDependencies": {
"@emotion/is-prop-valid": "*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"peerDependenciesMeta": {
"@emotion/is-prop-valid": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -4105,6 +4130,11 @@
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"node_modules/tslib": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA=="
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@ -13,6 +13,7 @@
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"axios": "^1.7.7",
"framer-motion": "^11.11.10",
"jwt-decode": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import { getAllUsers, getAllDocuments, getUserInfo } from '../../services/api';
import { getAllUsers, getAllDocuments, getUserInfo, createUser } from '../../services/api';
import DocumentUpload from '../documentUpload/DocumentUpload';
import UserCreate from '../UserCreate';
//import UserCreate from '../UserCreate';
import { useNavigate } from 'react-router-dom';
function AdminPanel() {
@ -12,6 +12,12 @@ function AdminPanel() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [isAdmin, setIsAdmin] = useState(false);
const [newUser, setNewUser] = useState({
name: '',
email: '',
password: '',
isAdmin: false
});
useEffect(() => {
checkAdminStatus();
@ -36,6 +42,7 @@ function AdminPanel() {
if (isAdmin) {
fetchData();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTab, isAdmin]);
const fetchData = async () => {
@ -70,6 +77,23 @@ function AdminPanel() {
return null;
}
const handleCreateUser = async (e) => {
e.preventDefault();
try {
await createUser(newUser);
setNewUser({
name: '',
email: '',
password: '',
isAdmin: false // Reset isAdmin too
});
fetchData();
} catch (err) {
setError('Failed to create user');
}
};
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="bg-white rounded-lg shadow">
@ -165,37 +189,78 @@ function AdminPanel() {
)}
{activeTab === 'users' && (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Role</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{users.map((user) => (
<tr key={user.id}>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{user.name}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{user.email}</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${user.isAdmin ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-800'}`}>
{user.isAdmin ? 'Admin' : 'User'}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div>
<UserCreate onUserCreated={fetchData} />
</div>
</div>
<>
<form onSubmit={handleCreateUser} className="mb-8">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<input
type="text"
placeholder="Name"
value={newUser.name}
onChange={(e) => setNewUser({ ...newUser, name: e.target.value })}
className="rounded border p-2"
/>
<input
type="email"
placeholder="Email"
value={newUser.email}
onChange={(e) => setNewUser({ ...newUser, email: e.target.value })}
className="rounded border p-2"
/>
<input
type="password"
placeholder="Password"
value={newUser.password}
onChange={(e) => setNewUser({ ...newUser, password: e.target.value })}
className="rounded border p-2"
/>
<div className="flex items-center">
<input
type="checkbox"
id="isAdmin"
checked={newUser.isAdmin}
onChange={(e) => setNewUser({ ...newUser, isAdmin: e.target.checked })}
className="mr-2"
/>
<label htmlFor="isAdmin">Is Admin</label>
</div>
<button
type="submit"
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
>
Create User
</button>
</div>
</form>
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Admin Status</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{users.map((user) => (
<tr key={user.id}>
<td className="px-6 py-4 whitespace-nowrap">{user.name}</td>
<td className="px-6 py-4 whitespace-nowrap">{user.email}</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-2 py-1 text-xs rounded-full ${
user.isAdmin ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'
}`}>
{user.isAdmin ? 'Admin' : 'User'}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap">
{/* Add actions if needed */}
</td>
</tr>
))}
</tbody>
</table>
</>
)}
{activeTab === 'upload' && <DocumentUpload />}

View File

@ -1,122 +1,237 @@
import { useEffect } from "react";
import "./lab.css";
// import { useEffect } from 'react';
// export default function Lab() {
// useEffect(() => {
// window.scrollTo({ top: 0, behavior: "smooth" })
// }, [])
// return (
// <div className="container mx-auto px-4">
// {/* Header */}
// <div className="mt-24 mb-5 md:mb-32 text-center">
// <h1 className="text-2xl capitalize underline">
// во нашата лабораторија се вршат
// </h1>
// </div>
// {/* Main Content */}
// <div className="flex flex-wrap gap-12 justify-around">
// {/* Concrete Testing Section */}
// <div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-72 mb-20 w-full">
// <div className="w-full md:w-1/2 px-8 py-6 text-center md:text-left bg-slate-100">
// <p className="mb-4">
// <strong className="text-xl block mb-2">
// Испитувањето на бетон
// </strong>
// е важен процес кој се користи за да се оцени квалитетот и издржливоста на бетонски конструкции.
// </p>
// <p>
// Испитувањето на бетонот е неопходен процес за осигурување на квалитет и безбедност на градежните проекти и инфраструктурата воопшто.
// Тоа помага во отстранивање на недостатоците и намалување на ризиците од евентуални пропаднувања на конструкциите.
// </p>
// </div>
// <div className="hidden md:block w-1/2">
// <img
// src="/kocki.webp"
// alt="Испитување на бетон"
// loading="lazy"
// className="max-w-full h-auto"
// />
// </div>
// </div>
// {/* Ore and Metal Testing Section */}
// <div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-72 mb-20 w-full">
// <div className="hidden md:block w-1/2">
// <img
// src="/lab.webp"
// alt="Испитување на руди и метали"
// loading="lazy"
// className="max-w-full h-auto"
// />
// </div>
// <div className="w-full md:w-1/2 px-8 py-6 text-center md:text-left bg-slate-100">
// <p className="mb-4">
// <strong className="text-xl block mb-2">
// Испитувањето на руди, метали и троски
// </strong>
// е важен процес во областа на геолошкото и металуршко инженерство, со цел да се анализираат и одредат својствата и составот на суровините и производите.
// </p>
// <p>
// Овие испитувања се изведуваат за да се осигура квалитетот и спецификациите на материјалите, како и за да се обезбеди безбедно и ефикасно користење и обработка на руди, метали и троски во различни индустрии и апликации.
// </p>
// </div>
// </div>
// {/* Steel Testing Section */}
// <div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-72 mb-20 w-full">
// <div className="w-full md:w-1/2 px-8 py-6 text-center md:text-left bg-slate-100">
// <p className="mb-4">
// <strong className="text-xl block mb-2">
// Испитувањето на челик
// </strong>
// е важен процес за одредување на квалитетот, издржливоста и други механички својства на челикот, кој се користи во разни индустрии и конструкции.
// </p>
// <p>
// Испитувањето на челик е неопходен процес за да се обезбеди квалитетот и безбедноста на производите и конструкциите кои го користат, како и за да се уверите дека челикот одговара на спецификациите и стандардите.
// </p>
// </div>
// <div className="hidden md:block w-1/2">
// <img
// src="/armatura.jpg"
// alt="Испитување на челик"
// loading="lazy"
// className="max-w-full h-auto"
// />
// </div>
// </div>
// {/* Laboratory Extraction Section */}
// <div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-72 mb-20 w-full">
// <div className="hidden md:block w-1/2">
// <img
// src="/geotehnika.webp"
// alt="Лабораториска екстракција"
// loading="lazy"
// className="max-w-full h-auto"
// />
// </div>
// <div className="w-full md:w-1/2 px-8 py-6 text-center md:text-left bg-slate-100">
// <p className="mb-4">
// <strong className="text-xl block mb-2">
// Лабораториската екстракција
// </strong>
// на метали или неметали од руди и троски е процес кој се користи за да се изолираат и оддели материјалите од суровините или отпадните производи, како што се рудите или троските, со цел да се добие чист метал или неметал.
// </p>
// </div>
// </div>
// </div>
// </div>
// );
// }
import { useEffect } from 'react';
export default function Lab() {
useEffect(() => {
window.scrollTo({ top: 0, behavior: "smooth" })
}, [])
return (
<>
<div className="wrapper">
<div className="heading sm:mb-5 md:mb-32">
<h1>во нашата лабораторија се вршат</h1>
<div className="min-h-screen bg-gray-50">
<div className="container mx-auto px-4 py-12">
{/* Header */}
<div className="mt-8 mb-16 text-center">
<h1 className="text-3xl md:text-4xl font-semibold capitalize text-gray-800 mb-4">
во нашата лабораторија се вршат
</h1>
<div className="w-24 h-1 bg-blue-500 mx-auto"></div>
</div>
<div className="text">
<div className="group md:bg-slate-300 sm:bg-none">
<div className="textBox md:ml-10 bg-slate-100 sm:ml-0">
<p>
<strong>Испитувањето на бетон</strong> е важен процес кој се
користи за да се оцени квалитетот и издржливоста на бетонски
конструкции.
</p>
<p>
Испитувањето на бетонот е неопходен процес за осигурување на
квалитет и безбедност на градежните проекти и инфраструктурата
воопшто. Тоа помага во отстранивање на недостатоците и
намалување на ризиците од евентуални пропаднувања на
конструкциите.
</p>
{/* Main Content */}
<div className="space-y-16">
{/* Concrete Testing Section */}
<div className="flex flex-col md:flex-row items-center gap-8 md:gap-16">
<div className="w-full md:w-1/2 p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-300">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
Испитувањето на бетон
</h2>
<div className="space-y-4 text-gray-600">
<p>
е важен процес кој се користи за да се оцени квалитетот и издржливоста на бетонски конструкции.
</p>
<p>
Испитувањето на бетонот е неопходен процес за осигурување на квалитет и безбедност на градежните проекти и инфраструктурата воопшто.
Тоа помага во отстранивање на недостатоците и намалување на ризиците од евентуални пропаднувања на конструкциите.
</p>
</div>
</div>
<div className="imgBox md:mr-10 my-10 sm:mr-0">
<img src="/kocki.webp" alt="" loading="lazy" />
</div>
</div>
<div className="group md:bg-slate-300 sm:bg-none">
<div className="imgBox md:ml-10 my-10 sm:ml-0">
<img
id="geotehnika"
src="/geotehnika.webp"
alt=""
<div className="w-full md:w-1/2">
<img
src="/kocki.webp"
alt="Испитување на бетон"
loading="lazy"
className="rounded-xl shadow-lg w-full h-[400px] object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
<div className="textBox md:mr-10 bg-slate-100 sm:mr-0">
<p>
<strong>Геотехничките испитувања</strong> се однесуваат на
процесот на испитување и анализирање на геолошките и
геотехничките својства на земјиштето за да се одреди неговата
способност да ги поддржат инфраструктурните конструкции и
проекти.
</p>
<p>
Геотехничките испитувања помагаат во разбирањето на
геотехничките услови на градежното место и обезбедуваат
информации за дизајнирање и изградба на стабилни и издржливи
инфраструктурни објекти и конструкции.
</p>
</div>
</div>
<div className="group md:bg-slate-300 sm:bg-none">
<div className="textBox md:ml-10 bg-slate-100 sm:ml-0">
<p>
<strong>Испитувањето на руди, метали и троски </strong>е важен
процес во областа на геолошкото и металуршко инженерство, со цел
да се анализираат и одредат својствата и составот на суровините
и производите.
</p>
<p>
Овие испитувања се изведуваат за да се осигура квалитетот и
спецификациите на материјалите, како и за да се обезбеди
безбедно и ефикасно користење и обработка на руди, метали и
троски во различни индустрии и апликации.
</p>
{/* Ore and Metal Testing Section */}
<div className="flex flex-col md:flex-row-reverse items-center gap-8 md:gap-16">
<div className="w-full md:w-1/2 p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-300">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
Испитувањето на руди, метали и троски
</h2>
<div className="space-y-4 text-gray-600">
<p>
е важен процес во областа на геолошкото и металуршко инженерство, со цел да се анализираат и одредат својствата и составот на суровините и производите.
</p>
<p>
Овие испитувања се изведуваат за да се осигура квалитетот и спецификациите на материјалите, како и за да се обезбеди безбедно и ефикасно користење и обработка на руди, метали и троски во различни индустрии и апликации.
</p>
</div>
</div>
<div className="imgBox md:mr-10 my-10 sm:mr-0">
<img id="geotehnika" src="/lab.webp" alt="" loading="lazy" />
<div className="w-full md:w-1/2">
<img
src="/lab.webp"
alt="Испитување на руди и метали"
loading="lazy"
className="rounded-xl shadow-lg w-full h-[400px] object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
</div>
<div className="group md:bg-slate-300 sm:bg-none">
<div className="imgBox md:ml-10 my-10 sm:ml-0">
<img id="geotehnika" src="/armatura.jpg" alt="" loading="lazy" />
{/* Steel Testing Section */}
<div className="flex flex-col md:flex-row items-center gap-8 md:gap-16">
<div className="w-full md:w-1/2 p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-300">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
Испитувањето на челик
</h2>
<div className="space-y-4 text-gray-600">
<p>
е важен процес за одредување на квалитетот, издржливоста и други механички својства на челикот, кој се користи во разни индустрии и конструкции.
</p>
<p>
Испитувањето на челик е неопходен процес за да се обезбеди квалитетот и безбедноста на производите и конструкциите кои го користат, како и за да се уверите дека челикот одговара на спецификациите и стандардите.
</p>
</div>
</div>
<div className="textBox md:mr-10 bg-slate-100 sm:mr-0">
<p>
<strong>Испитувањето на челик </strong>е важен процес за
одредување на квалитетот, издржливоста и други механички
својства на челикот, кој се користи во разни индустрии и
конструкции.
</p>
<p>
Испитувањето на челик е неопходен процес за да се обезбеди
квалитетот и безбедноста на производите и конструкциите кои го
користат, како и за да се уверите дека челикот одговара на
спецификациите и стандардите.
</p>
<div className="w-full md:w-1/2">
<img
src="/armatura.jpg"
alt="Испитување на челик"
loading="lazy"
className="rounded-xl shadow-lg w-full h-[400px] object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
</div>
<div className="group md:bg-slate-300 sm:bg-none">
<div className="textBox md:ml-10 bg-slate-100 sm:ml-0">
<p>
<strong>Лабораториската екстракција</strong> на метали или
неметали од руди и троски е процес кој се користи за да се
изолираат и оддели материјалите од суровините или отпадните
производи, како што се рудите или троските, со цел да се добие
чист метал или неметал.
</p>
{/* Laboratory Extraction Section */}
<div className="flex flex-col md:flex-row-reverse items-center gap-8 md:gap-16">
<div className="w-full md:w-1/2 p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-300">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
Лабораториската екстракција
</h2>
<div className="space-y-4 text-gray-600">
<p>
на метали или неметали од руди и троски е процес кој се користи за да се изолираат и оддели материјалите од суровините или отпадните производи, како што се рудите или троските, со цел да се добие чист метал или неметал.
</p>
</div>
</div>
<div className="imgBox md:mr-10 my-10 sm:mr-0">
<img id="geotehnika" src="/ekstrakcija.jpg" alt="" loading="lazy" />
<div className="w-full md:w-1/2">
<img
src="/geotehnika.webp"
alt="Лабораториска екстракција"
loading="lazy"
className="rounded-xl shadow-lg w-full h-[400px] object-cover hover:scale-105 transition-transform duration-300"
/>
</div>
</div>
</div>
</div >
</>
</div>
</div>
);
}
}

View File

@ -2,7 +2,7 @@ import { useState } from "react";
import { Dialog } from "@headlessui/react";
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
import { NavLink } from "react-router-dom";
import "./navbar.css";
const navigation = [
{ name: "Дома", href: "/" },
{ name: "За нас", href: "/about" },
@ -17,107 +17,117 @@ export default function Navbar() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
return (
<>
<div className="">
<div className="bg-white">
<header className="nav">
<nav
className="flex items-center justify-between p-6 lg:px-8"
aria-label="Global"
<div className="absolute w-full z-50">
<header className="relative bg-transparent">
<nav
className="container mx-auto flex items-center justify-between p-6 lg:px-8"
aria-label="Global"
>
{/* Logo */}
<div className="flex lg:flex-1">
<a href="/" className="flex items-center -m-1.5 p-1.5">
<img
className="h-12 w-auto hover:scale-105 transition-transform duration-300"
src="/imklogorgb.png"
alt="IMK logo"
/>
</a>
</div>
{/* Mobile menu button */}
<div className="flex lg:hidden">
<button
type="button"
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-white hover:bg-white/10 transition-colors duration-300"
onClick={() => setMobileMenuOpen(true)}
>
<div id="logo" className="">
<div className="flex lg:flex-1">
<a href="#" className="-m-1.5 p-1.5">
<span></span>
<img
className="h-14 w-auto"
src="/imklogorgb.png"
alt="logo"
/>
</a>
<span className="sr-only">Open main menu</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
{/* Desktop navigation */}
<div className="hidden lg:flex lg:gap-x-12">
{navigation.map((item) => (
<NavLink
key={item.name}
to={item.href}
className={({ isActive }) =>
`text-base font-semibold leading-6 transition-all duration-300
${isActive
? 'text-white border-b-2 border-white'
: 'text-gray-200 hover:text-white hover:border-b-2 hover:border-white/50'
}`
}
>
{item.name}
</NavLink>
))}
</div>
{/* TUF Logo */}
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
<a href="/" className="flex items-center -m-1.5 p-1.5">
<img
className="h-12 w-auto hover:scale-105 transition-transform duration-300"
src="/tuf.png"
alt="TUF logo"
/>
</a>
</div>
</nav>
{/* Mobile menu */}
<Dialog
as="div"
className="lg:hidden"
open={mobileMenuOpen}
onClose={setMobileMenuOpen}
>
<div className="fixed inset-0 z-50" />
<Dialog.Panel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-gradient-to-b from-blue-900 to-blue-800 px-6 py-6 sm:max-w-sm">
<div className="flex items-center justify-between">
<a href="/" className="-m-1.5 p-1.5">
<img
className="h-8 w-auto"
src="/imklogorgb.png"
alt="IMK logo"
/>
</a>
<button
type="button"
className="-m-2.5 rounded-md p-2.5 text-white hover:bg-white/10 transition-colors duration-300"
onClick={() => setMobileMenuOpen(false)}
>
<span className="sr-only">Close menu</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-white/10">
<div className="space-y-2 py-6">
{navigation.map((item) => (
<NavLink
key={item.name}
to={item.href}
className={({ isActive }) =>
`-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 transition-colors duration-300
${isActive
? 'text-white bg-white/10'
: 'text-gray-200 hover:bg-white/5 hover:text-white'
}`
}
onClick={() => setMobileMenuOpen(false)}
>
{item.name}
</NavLink>
))}
</div>
</div>
<div className="flex lg:hidden">
<button
type="button"
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
onClick={() => setMobileMenuOpen(true)}
>
<span className="sr-only">Open main menu</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="hidden lg:flex lg:gap-x-12 navitems">
{navigation.map((item) => (
<NavLink
key={item.name}
to={item.href}
className="text-lg font-semibold leading-6 text-gray-500"
>
{item.name}
</NavLink>
))}
</div>
<div id="logo-tuf" className="">
<div className="flex lg:flex-1">
<a href="#" className="-m-1.5 p-1.5">
<span></span>
<img
className="h-14 w-auto"
src="/tuf.png"
alt="tuf logo"
/>
</a>
</div>
</div>
</nav>
<Dialog
as="div"
className="lg:hidden"
open={mobileMenuOpen}
onClose={setMobileMenuOpen}
>
<div className="fixed inset-0 z-50" />
<Dialog.Panel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div className="flex items-center justify-between">
<NavLink href="#" className="-m-1.5 p-1.5">
<span className="sr-only">ИМК</span>
{/* <img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt=""
/> */}
</NavLink>
<button
type="button"
className="-m-2.5 rounded-md p-2.5 text-gray-700"
onClick={() => setMobileMenuOpen(false)}
>
<span className="sr-only">Close menu</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-gray-500/10">
<div className="space-y-2 py-6">
{navigation.map((item) => (
<NavLink
key={item.name}
to={item.href}
className="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
onClick={() => setMobileMenuOpen(false)}
>
{item.name}
</NavLink>
))}
</div>
</div>
</div>
</Dialog.Panel>
</Dialog>
</header>
</div>
</div>
</>
</div>
</Dialog.Panel>
</Dialog>
</header>
</div>
);
}
}

View File

@ -1,124 +1,195 @@
import './about.css'
// import './about.css'
// export default function About() {
// return (
// <>
// <div className="aboutGroup">
// {/* <div className="container"> */}
// <div className="aboutContainer">
// <h1 className="text-2xl text-center mt-32 font-bold tracking-tight text-gray-900 sm:text-4xl">За нас</h1>
// <p className="tracking-tight text-gray-900 sm:text-4xl mt-16">Компанијата Испитување на материјали и консултантство ДООЕЛ е основана во 2021 година. Главната дејност на ИМК ДООЕЛ е лабораториски испитувања во
// областа на градежништвото и индустријата, како и консултантски услуги во областа на индустријата. Со успешното работење во своите области и
// стручниот кадар кој компанијата го поседува, во 2022 година за компанијата интерес пројавува потенцијален партнер од Швајцарија. Во 2023
// година компанијата ИМК ДООЕЛ од домашна компанија прераснува во интернационална компанија со добивање на партнер од Швајцарија и
// прераснува во ИМК ДОО. Во истата година компанијата добива финансиска поддршка од старт ап фондот СЕКО, фонд кој го препозна квалитетот и
// визијата кој го поседуваат двајца млади претпиемачи. Лабораторијата е комплетно опремена да одговори на секој предизвик во областа на
// испитувањето на квалитетот на материјалите во градежната индсутрија со најмодерни инструменти за теренско и лабораториско испитување.
// Испитувањето на материјалите се врши според најнови EN и МКС стандарди.</p>
// </div>
// <div className="form-container">
// <div className="mx-auto max-w-2xl text-center">
// <h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Станете дел од нашиот тим</h2>
// </div>
// <form action="https://formsubmit.co/taratur@gmail.com"
// enctype='multipart/form-data'
// method="POST" className="mx-auto mt-16 max-w-xl sm:mt-20">
// <div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
// <div>
// <label htmlFor="first-name" className="block text-sm font-semibold leading-6 text-gray-900">
// Име
// </label>
// <div className="mt-2.5">
// <input
// type="text"
// name="first-name"
// id="first-name"
// autoComplete="given-name"
// className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
// />
// </div>
// </div>
// <div>
// <label htmlFor="last-name" className="block text-sm font-semibold leading-6 text-gray-900">
// Презиме
// </label>
// <div className="mt-2.5">
// <input
// type="text"
// name="last-name"
// id="last-name"
// autoComplete="family-name"
// className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
// />
// </div>
// </div>
// <div className="sm:col-span-2">
// <label htmlFor="email" className="block text-sm font-semibold leading-6 text-gray-900">
// Мејл
// </label>
// <div className="mt-2.5">
// <input
// type="email"
// name="email"
// id="email"
// autoComplete="email"
// className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
// />
// </div>
// </div>
// <div className="sm:col-span-2">
// <label htmlFor="message" className="block text-sm font-semibold leading-6 text-gray-900">
// Порака
// </label>
// <div className="mt-2.5">
// <textarea
// name="message"
// id="message"
// rows={4}
// className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
// defaultValue={''}
// />
// </div>
// </div>
// <div className="sm:col-span-2">
// <label htmlFor="attachment" className="block text-lg font-semibold leading-6 text-gray-900 mb-4">
// Прокачетего вашето CV (5mb max)
// </label>
// <input type="file" name="attachment" id='attachment' accept=".pdf, image/jpeg, .doc, .odt" />
// </div>
// {/* <Switch.Group as="div" className="flex gap-x-4 sm:col-span-2">
// </Switch.Group> */}
// </div>
// <input type="hidden" name="_next" value="https://imk-azure.vercel.app/"></input>
// <div className="mt-10">
// <button
// type="submit"
// className="block w-full rounded-md bg-gray-500 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-sm hover:bg-gray-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500"
// >
// Испрати
// </button>
// </div>
// </form>
// {/* </div > */}
// </div>
// </div>
// </>
// )
// }
import { SectionHeader } from '../../shared/SectionHeader';
import { Button } from '../../shared/Button';
export default function About() {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-white">
{/* Hero Section */}
<div className="relative h-[60vh] overflow-hidden">
<div className="absolute inset-0">
<img
src="/about-hero.jpg"
alt="About Us"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-blue-900/90 to-blue-600/80" />
</div>
<div className="relative container mx-auto px-4 h-full flex items-center">
<div className="max-w-3xl">
<h1 className="text-4xl md:text-6xl font-bold text-white mb-6">
За Нас
</h1>
<p className="text-xl text-gray-200 mb-8">
Повеќе од 15 години искуство во обезбедување квалитет
</p>
</div>
</div>
</div>
{/* Content Sections */}
<div className="container mx-auto px-4 py-16">
<SectionHeader
title="Нашата Мисија"
subtitle="Посветени сме на обезбедување највисок квалитет во нашата работа"
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="bg-white rounded-xl shadow-lg p-8">
<h3 className="text-2xl font-semibold text-gray-800 mb-4">
Визија
</h3>
<p className="text-gray-600">
Да бидеме водечка компанија во обезбедување на квалитет и сигурност во градежништвото.
</p>
</div>
<div className="bg-white rounded-xl shadow-lg p-8">
<h3 className="text-2xl font-semibold text-gray-800 mb-4">
Вредности
</h3>
<p className="text-gray-600">
Професионалност, посветеност и иновација во секој проект.
</p>
</div>
</div>
</div>
return (
<>
<div className="aboutGroup">
{/* <div className="container"> */}
<div className="aboutContainer">
<h1 className="text-2xl text-center mt-32 font-bold tracking-tight text-gray-900 sm:text-4xl">За нас</h1>
<p className="tracking-tight text-gray-900 sm:text-4xl mt-16">Компанијата Испитување на материјали и консултантство ДООЕЛ е основана во 2021 година. Главната дејност на ИМК ДООЕЛ е лабораториски испитувања во
областа на градежништвото и индустријата, како и консултантски услуги во областа на индустријата. Со успешното работење во своите области и
стручниот кадар кој компанијата го поседува, во 2022 година за компанијата интерес пројавува потенцијален партнер од Швајцарија. Во 2023
година компанијата ИМК ДООЕЛ од домашна компанија прераснува во интернационална компанија со добивање на партнер од Швајцарија и
прераснува во ИМК ДОО. Во истата година компанијата добива финансиска поддршка од старт ап фондот СЕКО, фонд кој го препозна квалитетот и
визијата кој го поседуваат двајца млади претпиемачи. Лабораторијата е комплетно опремена да одговори на секој предизвик во областа на
испитувањето на квалитетот на материјалите во градежната индсутрија со најмодерни инструменти за теренско и лабораториско испитување.
Испитувањето на материјалите се врши според најнови EN и МКС стандарди.</p>
</div>
<div className="form-container">
<div className="mx-auto max-w-2xl text-center">
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Станете дел од нашиот тим</h2>
</div>
<form action="https://formsubmit.co/taratur@gmail.com"
enctype='multipart/form-data'
method="POST" className="mx-auto mt-16 max-w-xl sm:mt-20">
<div className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
<div>
<label htmlFor="first-name" className="block text-sm font-semibold leading-6 text-gray-900">
Име
</label>
<div className="mt-2.5">
<input
type="text"
name="first-name"
id="first-name"
autoComplete="given-name"
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div>
<label htmlFor="last-name" className="block text-sm font-semibold leading-6 text-gray-900">
Презиме
</label>
<div className="mt-2.5">
<input
type="text"
name="last-name"
id="last-name"
autoComplete="family-name"
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="email" className="block text-sm font-semibold leading-6 text-gray-900">
Мејл
</label>
<div className="mt-2.5">
<input
type="email"
name="email"
id="email"
autoComplete="email"
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="message" className="block text-sm font-semibold leading-6 text-gray-900">
Порака
</label>
<div className="mt-2.5">
<textarea
name="message"
id="message"
rows={4}
className="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
defaultValue={''}
/>
</div>
</div>
<div className="sm:col-span-2">
<label htmlFor="attachment" className="block text-lg font-semibold leading-6 text-gray-900 mb-4">
Прокачетего вашето CV (5mb max)
</label>
<input type="file" name="attachment" id='attachment' accept=".pdf, image/jpeg, .doc, .odt" />
</div>
{/* <Switch.Group as="div" className="flex gap-x-4 sm:col-span-2">
</Switch.Group> */}
</div>
<input type="hidden" name="_next" value="https://imk-azure.vercel.app/"></input>
<div className="mt-10">
<button
type="submit"
className="block w-full rounded-md bg-gray-500 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-sm hover:bg-gray-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500"
>
Испрати
</button>
</div>
</form>
{/* </div > */}
</div>
</div>
</>
)
{/* CTA Section */}
<div className="bg-blue-600 text-white py-24">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-8">
Започнете го вашиот проект со нас
</h2>
<Button variant="secondary">
Контактирајте нѐ
</Button>
</div>
</div>
</div>
);
}

View File

@ -1,235 +1,190 @@
import { NavLink } from "react-router-dom";
import "./home.css";
import { motion } from "framer-motion"; // You'll need to install framer-motion
import { ArrowRightIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
const Home = () => {
const serviceCards = [
{
title: "Лабораториски услуги",
description: "Професионални лабораториски испитувања со најсовремена опрема",
image: "/labfinal.webp",
link: "/lab",
services: [
"Испитување на бетон",
"Геотехнички испитувања",
"Испитување на челик",
"Испитување на руди, метали и троски",
"Лабораториска екстракција од руди и троски"
]
},
// ... other service cards
];
export default function Home() {
return (
<>
<div className="homeContainer">
<div className="bannerTop">
<div className="slogan md:bg-slate-300 w-full py-10 sm:bg-none">
<h1 className="">
ИМК: Вашиот партнер во контролата на безбедно градење и квалитетно
живеење
</h1>
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-white">
{/* Hero Section with Parallax */}
<div className="relative h-[90vh] overflow-hidden">
<div className="absolute inset-0">
<img
src="/hero-background.jpg"
alt="Laboratory Background"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-r from-blue-900/90 to-blue-600/80" />
</div>
<div className="relative container mx-auto px-4 h-full flex items-center">
<div className="max-w-3xl">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-4xl md:text-6xl font-bold text-white mb-6"
>
Вашиот партнер во контролата на безбедно градење
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="text-xl text-gray-200 mb-8"
>
Професионални лабораториски услуги со најсовремена опрема и експертиза
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="flex gap-4"
>
<NavLink
to="/contact"
className="bg-blue-500 hover:bg-blue-600 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300"
>
Контактирајте нѐ
</NavLink>
<NavLink
to="/services"
className="bg-white/10 hover:bg-white/20 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300"
>
Дознајте повеќе
</NavLink>
</motion.div>
</div>
</div>
</div>
<div className="imgHelper">
<div className="">
<div className="grid grid-cols-1 grid-rows-1 md:grid-cols-3 gap-16 mt-16">
<div className="block rounded-lg bg-white shadow-[0_2px_15px_-3px_rgba(0,0,0,0.07),0_10px_20px_-2px_rgba(0,0,0,0.04)] dark:bg-neutral-700">
<NavLink to="/lab">
<div
className="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light"
>
<img
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
objectPosition: 'center'
}}
className="rounded-t-lg"
src="/labfinal.webp"
alt=""
loading="lazy"
/>
<a href="#!">
<div className="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
<div className="p-6">
<h5 className="mb-2 text-xl text-center font-medium leading-tight text-neutral-800 dark:text-neutral-50">
Лабораториски услуги
</h5>
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">
Some quick example text to build on the card title and
make up the bulk of the card's content.
</p> */}
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">Нашата лабораторија ви нуди...</p> */}
{/* <button
type="button"
className="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
data-te-ripple-init
data-te-ripple-color="light"
>
Прочитај повеќе
</button> */}
</div>
</NavLink>
</div>
<NavLink to="/ultrasound">
<div className="block rounded-lg bg-white shadow-[0_2px_15px_-3px_rgba(0,0,0,0.07),0_10px_20px_-2px_rgba(0,0,0,0.04)] dark:bg-neutral-700">
<div
className="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light"
>
<img
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
objectPosition: 'center'
}}
className="rounded-t-lg"
src="wallscener.jpeg"
alt=""
loading="lazy"
/>
<a href="#!">
<div className="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
<div className="p-6">
<h5 className="mb-2 text-xl text-center font-medium leading-tight text-neutral-800 dark:text-neutral-50">
Испитување со ултразвук
</h5>
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">Најсовремена радарска технологија.</p> */}
{/* Stats Section */}
<div className="container mx-auto px-4 py-16">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{[
{ number: "15+", label: "Години искуство" },
{ number: "1000+", label: "Задоволни клиенти" },
{ number: "5000+", label: "Завршени проекти" },
{ number: "100%", label: "Задоволство" },
].map((stat) => (
<div key={stat.label} className="text-center">
<div className="text-4xl font-bold text-blue-600 mb-2">{stat.number}</div>
<div className="text-gray-600">{stat.label}</div>
</div>
))}
</div>
</div>
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">
Some quick example text to build on the card title and make
up the bulk of the card's content.
</p> */}
{/* <button
type="button"
className="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
data-te-ripple-init
data-te-ripple-color="light"
>
Прочитај повеќе
</button> */}
{/* Services Section */}
<div className="bg-gray-100 py-24">
<div className="container mx-auto px-4">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Нашите Услуги
</h2>
<div className="w-24 h-1 bg-blue-500 mx-auto"></div>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{serviceCards.map((card) => (
<NavLink
key={card.title}
to={card.link}
className="group bg-white rounded-2xl shadow-lg overflow-hidden hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1"
>
<div className="relative h-56 overflow-hidden">
<img
src={card.image}
alt={card.title}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
<h3 className="absolute bottom-4 left-4 text-xl font-semibold text-white">
{card.title}
</h3>
</div>
<div className="p-6">
<p className="text-gray-600 mb-4">{card.description}</p>
<ul className="space-y-2">
{card.services.slice(0, 3).map((service, index) => (
<li
key={index}
className="flex items-center text-gray-700"
>
<CheckCircleIcon className="h-5 w-5 text-blue-500 mr-2" />
{service}
</li>
))}
</ul>
<div className="mt-4 flex items-center text-blue-500 font-semibold">
Дознајте повеќе
<ArrowRightIcon className="h-5 w-5 ml-2 group-hover:translate-x-2 transition-transform duration-300" />
</div>
</div>
</NavLink>
))}
</div>
</div>
</div>
<div className="block rounded-lg bg-white shadow-[0_2px_15px_-3px_rgba(0,0,0,0.07),0_10px_20px_-2px_rgba(0,0,0,0.04)] dark:bg-neutral-700">
<NavLink to="/consulting">
<div
className="relative overflow-hidden bg-cover bg-no-repeat"
data-te-ripple-init
data-te-ripple-color="light"
>
<img
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
objectPosition: 'center'
}}
className="rounded-t-lg"
src="/consulting2.jpg"
alt=""
loading="lazy"
/>
<a href="#!">
<div className="absolute bottom-0 left-0 right-0 top-0 h-full w-full overflow-hidden bg-[hsla(0,0%,98%,0.15)] bg-fixed opacity-0 transition duration-300 ease-in-out hover:opacity-100"></div>
</a>
</div>
<div className="p-6">
<h5 className="mb-2 text-xl text-center font-medium leading-tight text-neutral-800 dark:text-neutral-50">
Консултантски услуги
</h5>
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">Проектна документација, елаборати</p> */}
{/* <p className="mb-4 text-base text-neutral-600 dark:text-neutral-200">
Some quick example text to build on the card title and make
up the bulk of the card's content.
</p> */}
{/* <NavLink to={"/consulting"}> */}
{/* <button
type="button"
className="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
data-te-ripple-init
data-te-ripple-color="light"
>
Прочитај повеќе
</button> */}
</div>
</NavLink>
</div>
{/* Featured Projects/Clients */}
<div className="container mx-auto px-4 py-24">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Наши Клиенти
</h2>
<div className="w-24 h-1 bg-blue-500 mx-auto mb-8"></div>
<p className="text-gray-600 max-w-2xl mx-auto">
Горди сме на довербата која ни ја укажуваат нашите клиенти
</p>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
{/* Add client logos here */}
{[1, 2, 3, 4].map((index) => (
<div
key={index}
className="bg-white p-8 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
>
<img
src={`/client-${index}.png`}
alt={`Client ${index}`}
className="w-full h-20 object-contain grayscale hover:grayscale-0 transition-all duration-300"
/>
</div>
</div>
))}
</div>
<div className="bannerBottom mt-16">
<div className="md:bg-slate-300 w-full py-1 my-32 sm:bg-none">
<h2>
Осигурајте го Вашиот бизнис план со нас и дозволете ни да ви
помогнеме во Вашиот успех
</h2>
</div>
</div>
<div className="someclass">
<div className="team">
{/* <h1>Станете дел од нашиот тим</h1> */}
<img src="/naum2.webp" alt="" />
</div>
</div>
{/* slide show start */}
{/* slide show end */}
<div className="listCards">
<div className="serviceCard">
<NavLink to="/lab">
<div>
<h1>Лабораторија</h1>
</div>
<ul>
<li>Испитување на бетон</li>
<li>Геотехнички испитувања</li>
<li>Испитување на челик</li>
<li>Испитување на руди, метали и троски</li>
<li>Лабораториска екстракција од руди и троски</li>
</ul>
</NavLink>
</div>
<div className="serviceCard">
<NavLink to="/ultrasound">
<div>
<h1>Испитување со ултразвук</h1>
</div>
<ul>
<li>
Испитување на број и распоред на арматурни шипки
</li>
<li>Детектирање на електрична инсталација</li>
<li>Детектирање на водоводна инсталација и пукнати цевки во ѕид</li>
</ul>
</NavLink>
</div>
<div className="serviceCard">
<NavLink to="/consulting">
<div>
<h1>Консултанстски услуги</h1>
</div>
<ul>
<li>Изработка на Б интегрирани дозволи</li>
<li>Изработка на А интегрирани дозволи</li>
<li>Изработка на проценка на влијанија на животна средина</li>
<li>
Изработка на проектна документација за производствени погони
</li>
<li>
Изработка на cost efficiency проекти за производствени погони
</li>
<li>
Изработка на елаборати за финансиска исплатливост на
производствени процеси
</li>
</ul>
</NavLink>
</div>
</div>
{/* CTA Section */}
<div className="bg-blue-600 text-white py-24">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-8">
Спремни сме да ви помогнеме во вашиот следен проект
</h2>
<NavLink
to="/contact"
className="inline-block bg-white text-blue-600 px-8 py-3 rounded-full font-semibold hover:bg-gray-100 transition-colors duration-300"
>
Контактирајте нѐ
</NavLink>
</div>
</div >
</>
</div>
</div>
);
};
export default Home;
}

View File

@ -14,7 +14,15 @@ api.interceptors.request.use((config) => {
}
return config;
});
export const createUser = (userData) => api.post('/admin/users', userData);
// export const createUser = (userData) => api.post('/admin/users', userData);
export const createUser = (userData) => {
return api.post('/admin/users', {
name: userData.name,
email: userData.email,
password: userData.password,
isAdmin: userData.isAdmin // Add this line
});
};
export const login = (username, password) => api.post('/auth/login', { username, password });
export const shareDocument = (documentId, userIds) => api.post(`/admin/documents/${documentId}/share`, { userIds });
export const updateDocumentStatus = (documentId, status) => api.put(`/admin/documents/${documentId}/status`, { status });

View File

@ -0,0 +1,18 @@
// Reusable button component
export function Button({ variant = 'primary', children, ...props }) {
const baseStyles = "px-8 py-3 rounded-full font-semibold transition-colors duration-300";
const variants = {
primary: "bg-blue-600 hover:bg-blue-700 text-white",
secondary: "bg-white/10 hover:bg-white/20 text-white",
outline: "border-2 border-blue-600 text-blue-600 hover:bg-blue-50"
};
return (
<button
className={`${baseStyles} ${variants[variant]}`}
{...props}
>
{children}
</button>
);
}

View File

@ -0,0 +1,17 @@
// Reusable section header component
// eslint-disable-next-line react/prop-types
export function SectionHeader({ title, subtitle }) {
return (
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-800 mb-4">
{title}
</h2>
<div className="w-24 h-1 bg-blue-600 mx-auto mb-8"></div>
{subtitle && (
<p className="text-gray-600 max-w-2xl mx-auto">
{subtitle}
</p>
)}
</div>
);
}

View File

@ -0,0 +1,20 @@
export const colors = {
primary: {
light: '#3B82F6', // blue-500
DEFAULT: '#2563EB', // blue-600
dark: '#1D4ED8', // blue-700
darker: '#1E40AF' // blue-800
},
background: {
light: '#F9FAFB', // gray-50
DEFAULT: '#F3F4F6', // gray-100
dark: '#E5E7EB' // gray-200
},
text: {
primary: '#1F2937', // gray-800
secondary: '#4B5563', // gray-600
light: '#9CA3AF' // gray-400
},
white: '#FFFFFF',
black: '#000000'
}

View File

@ -0,0 +1,25 @@
export const commonStyles = {
// Container
container: "container mx-auto px-4",
// Section Headers
sectionHeader: "text-center mb-16",
sectionTitle: "text-3xl md:text-4xl font-bold text-gray-800 mb-4",
sectionDivider: "w-24 h-1 bg-blue-600 mx-auto",
// Cards
card: "bg-white rounded-xl shadow-lg hover:shadow-xl transition-all duration-300",
// Buttons
primaryButton: "bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300",
secondaryButton: "bg-white/10 hover:bg-white/20 text-white px-8 py-3 rounded-full font-semibold transition-colors duration-300",
// Gradients
primaryGradient: "bg-gradient-to-r from-blue-900/90 to-blue-600/80",
// Text
heading1: "text-4xl md:text-6xl font-bold",
heading2: "text-3xl md:text-4xl font-bold",
heading3: "text-2xl font-semibold",
paragraph: "text-gray-600"
}