Fix-projects #8
@@ -1,21 +1,7 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styles from '@styles/BlogCard.module.scss';
|
import styles from '@styles/BlogCard.module.scss';
|
||||||
|
|
||||||
export interface BlogPostProps {
|
import type {BlogPostProps} from '../untils/BlogPostProps';
|
||||||
id: string;
|
|
||||||
slug: string;
|
|
||||||
title: string;
|
|
||||||
excerpt: string;
|
|
||||||
image: string;
|
|
||||||
category: string;
|
|
||||||
date: string;
|
|
||||||
author: string;
|
|
||||||
commentCount: number;
|
|
||||||
readTime: string;
|
|
||||||
featured?: boolean;
|
|
||||||
tags: string[];
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BlogCardProps {
|
interface BlogCardProps {
|
||||||
post: BlogPostProps;
|
post: BlogPostProps;
|
||||||
|
|||||||
@@ -1,32 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import style from '@styles/Project.module.scss'
|
import style from '@styles/Project.module.scss'
|
||||||
|
import type {ProjectTech, Category, ProjectProps } from '../untils/ProjectProps'
|
||||||
export interface ProjectTech {
|
|
||||||
name: string;
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProjectProps {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
image: string;
|
|
||||||
category: Category[];
|
|
||||||
featured?: boolean;
|
|
||||||
technologies: ProjectTech[];
|
|
||||||
links: {
|
|
||||||
github?: string;
|
|
||||||
demo?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Category {
|
|
||||||
[key: string]: string;
|
|
||||||
fullName: string;
|
|
||||||
shortName: string;
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProjectCardProps {
|
interface ProjectCardProps {
|
||||||
project: ProjectProps;
|
project: ProjectProps;
|
||||||
|
|||||||
+149
-137
@@ -1,154 +1,166 @@
|
|||||||
import type { ProjectProps } from './ProjectCard';
|
import type { ProjectProps } from '../untils/ProjectProps';
|
||||||
|
|
||||||
import style from '@styles/Project.module.scss'
|
import style from '@styles/Project.module.scss'
|
||||||
|
|
||||||
|
|
||||||
interface ProjectModalProps {
|
interface ProjectModalProps {
|
||||||
project: ProjectProps | null;
|
project: ProjectProps | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProjectModal: React.FC<ProjectModalProps> = ({ project }) => {
|
export const ProjectModal: React.FC<ProjectModalProps> = ({ project }) => {
|
||||||
if (!project) return null;
|
if (!project) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal fade" id="shadowguardianModal" tabIndex={-1} aria-labelledby="shadowguardianModalLabel" aria-hidden="true">
|
<div className="modal fade" id="shadowguardianModal" tabIndex={-1} aria-labelledby="shadowguardianModalLabel" aria-hidden="true">
|
||||||
<div className="modal-dialog modal-xl modal-dialog-scrollable">
|
<div className="modal-dialog modal-xl modal-dialog-scrollable">
|
||||||
<div className={`modal-content ${style.modalContent}`}>
|
<div className={`modal-content ${style.modalContent}`}>
|
||||||
<div className="modal-header">
|
<div className={`modal-header ${style.modalHeader}`}>
|
||||||
<h5 className={style.modalHeader} id="shadowguardianModalLabel">
|
<h5 className={style.modalHeader} id="shadowguardianModalLabel">
|
||||||
{project.title}
|
{project.title}
|
||||||
</h5>
|
</h5>
|
||||||
<button type="button" className={`btn-close ${style.btnClose}`} data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" className={`btn-close ${style.btnClose}`} data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div className={`modal-body ${style.modalBody}`}>
|
<div className={`modal-body ${style.modalBody}`}>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<img src="/api/placeholder/1000/400" className="img-fluid rounded mb-3" alt="ShadowGuardian Project" />
|
<img src={project.image} className="img-fluid rounded mb-3" alt={project.title} />
|
||||||
<div className="row">
|
<div className={`row ${style.row}`}>
|
||||||
<div className="col-md-8">
|
<div className="col-md-8">
|
||||||
<p>ShadowGuardian is a comprehensive security monitoring system designed for both residential and commercial applications. Built on a foundation of STM32 microcontrollers, it provides reliable, secure monitoring with extremely low power consumption, allowing for battery operation of up to 2 years.</p>
|
{
|
||||||
<p>The system features end-to-end encryption for all communications, ensuring that sensitive security data remains private. Its modular architecture allows for easy expansion with additional sensors and integration with existing home automation systems.</p>
|
project.projectDetails ? project.projectDetails.descriptions.map((desc, index) => (
|
||||||
</div>
|
<p key={index} className="mb-3">{desc}</p>
|
||||||
<div className="col-md-4">
|
)) :
|
||||||
<div className="card h-100">
|
<p>{project.description}</p>
|
||||||
<div className="card-header">
|
}
|
||||||
<h5 className="mb-0">Project Overview</h5>
|
</div>
|
||||||
</div>
|
<div className="col-md-4">
|
||||||
<div className="card-body">
|
<div className={`card h-100 ${style.card}`}>
|
||||||
<p><strong>Duration:</strong> 6 months</p>
|
<div className={`card-header ${style.cardHeader}`}>
|
||||||
<p><strong>Role:</strong> Lead Developer</p>
|
<h5 className="mb-0">Project Overview</h5>
|
||||||
<p><strong>Status:</strong> Completed</p>
|
</div>
|
||||||
<p><strong>Client:</strong> ConnectedWorld Technologies</p>
|
<div className="card-body">
|
||||||
|
{project.projectDetails && project.projectDetails.startDate && project.projectDetails.endDate ? (
|
||||||
|
<p><strong>Duration:</strong> {new Date(project.projectDetails.startDate).toLocaleDateString()} - {new Date(project.projectDetails.endDate).toLocaleDateString()}</p>
|
||||||
|
) : (
|
||||||
|
<p><strong>Duration:</strong> Ongoing</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
project.projectDetails && project.projectDetails.role ? (
|
||||||
|
<p><strong>Role:</strong> {project.projectDetails.role}</p>
|
||||||
|
) : (
|
||||||
|
<p><strong>Role:</strong> Developer</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
project.projectDetails && project.projectDetails.client ? (
|
||||||
|
<p><strong>Client:</strong> {project.projectDetails.client}</p>
|
||||||
|
) : (
|
||||||
|
<p><strong>Client:</strong> Internal Project</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
project.projectDetails?.keyFeatures && project.projectDetails.keyFeatures.length > 0 && (
|
||||||
|
<>
|
||||||
|
<h4 className="mt-4 mb-3">Key Features</h4>
|
||||||
|
{
|
||||||
|
project.projectDetails?.keyFeatures.map((feature, index) => (
|
||||||
|
<p key={index} className="mb-2">
|
||||||
|
<i className="fas fa-check-circle text-success me-2"></i>
|
||||||
|
{feature}
|
||||||
|
</p>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 className="mt-4 mb-3">Technologies Used</h4>
|
||||||
|
<div className="mb-4">
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="devicon-cplusplus-plain tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">C++</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-microchip tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">STM32F4</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-wifi tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">ESP32</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-shield-alt tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">AES-256</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="devicon-react-original tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">React Native</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-broadcast-tower tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">BLE 5.0</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-network-wired tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">Zigbee</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-server tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">Node.js</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="fas fa-database tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">PostgreSQL</span>
|
||||||
|
</span>
|
||||||
|
<span className="tech-chip">
|
||||||
|
<i className="devicon-docker-plain tech-chip-icon"></i>
|
||||||
|
<span className="tech-chip-name">Docker</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
project.projectDetails?.gallery && project.projectDetails?.gallery.length > 0 && (
|
||||||
|
<>
|
||||||
|
<h4 className="mt-4 mb-3">Gallery</h4>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-4 col-6">
|
||||||
|
{
|
||||||
|
project.projectDetails.gallery.map((image, index) => (
|
||||||
|
<div key={index} className="gallery-item">
|
||||||
|
<img src={image} alt={`Gallery Image ${index + 1}`} className="gallery-image"></img>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className={`modal-footer ${style.modalFooter}`}>
|
||||||
|
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
||||||
|
<i className="fab fa-github btn-icon"></i>Source Code
|
||||||
|
</a>
|
||||||
|
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
||||||
|
<i className="fas fa-external-link-alt btn-icon"></i>Live Demo
|
||||||
|
</a>
|
||||||
|
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
||||||
|
<i className="fas fa-book btn-icon"></i>Documentation
|
||||||
|
</a>
|
||||||
|
<button type="button" className={`btn btn-secondary`} data-bs-dismiss="modal">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 className="mt-4 mb-3">Key Features</h4>
|
|
||||||
<ul className="features-list">
|
|
||||||
<li>Military-grade AES-256 encryption for all data transmission</li>
|
|
||||||
<li>Ultra-low power consumption with intelligent sleep modes</li>
|
|
||||||
<li>Modular sensor architecture supporting motion, contact, glass-break, and environmental sensors</li>
|
|
||||||
<li>Local processing to reduce cloud dependency and improve response times</li>
|
|
||||||
<li>Mesh networking for extended coverage without Wi-Fi dependencies</li>
|
|
||||||
<li>Real-time notifications via mobile app (iOS and Android)</li>
|
|
||||||
<li>Integration with popular home automation platforms including HomeKit, Google Home, and Alexa</li>
|
|
||||||
<li>Tamper detection and notification system</li>
|
|
||||||
<li>Optional cellular backup connection for critical deployments</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4 className="mt-4 mb-3">Technologies Used</h4>
|
|
||||||
<div className="mb-4">
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="devicon-cplusplus-plain tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">C++</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-microchip tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">STM32F4</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-wifi tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">ESP32</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-shield-alt tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">AES-256</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="devicon-react-original tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">React Native</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-broadcast-tower tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">BLE 5.0</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-network-wired tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">Zigbee</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-server tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">Node.js</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="fas fa-database tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">PostgreSQL</span>
|
|
||||||
</span>
|
|
||||||
<span className="tech-chip">
|
|
||||||
<i className="devicon-docker-plain tech-chip-icon"></i>
|
|
||||||
<span className="tech-chip-name">Docker</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 className="mt-4 mb-3">Gallery</h4>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="ShadowGuardian Hub" className="gallery-image"></img>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="ShadowGuardian Sensor" className="gallery-image"></img>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="Mobile App Dashboard" className="gallery-image" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="Door Sensor Installation" className="gallery-image" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="System Architecture Diagram" className="gallery-image" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-4 col-6">
|
|
||||||
<div className="gallery-item">
|
|
||||||
<img src="/api/placeholder/300/300" alt="PCB Design" className="gallery-image" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={`modal-footer ${style.modalFooter}`}>
|
|
||||||
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
|
||||||
<i className="fab fa-github btn-icon"></i>Source Code
|
|
||||||
</a>
|
|
||||||
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
|
||||||
<i className="fas fa-external-link-alt btn-icon"></i>Live Demo
|
|
||||||
</a>
|
|
||||||
<a href="#" className={`btn btn-outline-secondary ${style.btnOutlineSecondary}`}>
|
|
||||||
<i className="fas fa-book btn-icon"></i>Documentation
|
|
||||||
</a>
|
|
||||||
<button type="button" className={`btn btn-secondary`} data-bs-dismiss="modal">Close</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
};
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { BlogPostProps } from "../components/BlogCard";
|
import type {BlogPostProps} from '../untils/BlogPostProps'
|
||||||
|
|
||||||
export const blogPostsData: BlogPostProps[] = [
|
export const blogPostsData: BlogPostProps[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ProjectProps, Category } from "../components/ProjectCard";
|
import type { ProjectProps, Category } from "../untils/ProjectProps";
|
||||||
|
|
||||||
type CategoryMap = Record<string, Category>
|
type CategoryMap = Record<string, Category>
|
||||||
export const Categories: CategoryMap = {
|
export const Categories: CategoryMap = {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { PageHeader } from '../components/PageHeader';
|
import { PageHeader } from '../components/PageHeader';
|
||||||
import { ProjectCard, type ProjectProps } from '../components/ProjectCard';
|
import { ProjectCard } from '../components/ProjectCard';
|
||||||
import { ProjectModal } from '../components/ProjectModal';
|
import { ProjectModal } from '../components/ProjectModal';
|
||||||
import { projectsData, Categories } from '../data/projectsData';
|
import { projectsData, Categories } from '../data/projectsData';
|
||||||
|
import type {ProjectProps} from '../untils/ProjectProps';
|
||||||
|
|
||||||
import style from '@styles/Project.module.scss'
|
import style from '@styles/Project.module.scss'
|
||||||
|
|
||||||
@@ -15,6 +16,10 @@ export const Projects = () => {
|
|||||||
? projectsData
|
? projectsData
|
||||||
: projectsData.filter(project => project.category.some(cat => cat.shortName.toLowerCase() === activeFilter));
|
: projectsData.filter(project => project.category.some(cat => cat.shortName.toLowerCase() === activeFilter));
|
||||||
|
|
||||||
|
|
||||||
|
if (selectedProject == null && filteredProjects.length > 0)
|
||||||
|
setSelectedProject(filteredProjects[0]);
|
||||||
|
|
||||||
const categories = Categories;
|
const categories = Categories;
|
||||||
|
|
||||||
const featuredProject = projectsData.find(project => project.featured);
|
const featuredProject = projectsData.find(project => project.featured);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export interface BlogPostProps {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
excerpt: string;
|
||||||
|
image: string;
|
||||||
|
category: string;
|
||||||
|
date: string;
|
||||||
|
author: string;
|
||||||
|
commentCount: number;
|
||||||
|
readTime: string;
|
||||||
|
featured?: boolean;
|
||||||
|
tags: string[];
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
export interface ProjectProps {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
projectDetails?: ProjectDetails;
|
||||||
|
image: string;
|
||||||
|
category: Category[];
|
||||||
|
featured?: boolean;
|
||||||
|
technologies: ProjectTech[];
|
||||||
|
links: {
|
||||||
|
github?: string;
|
||||||
|
demo?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectDetails {
|
||||||
|
descriptions: string[];
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
dateFormatted?: string;
|
||||||
|
role: string;
|
||||||
|
status: string;
|
||||||
|
client: string;
|
||||||
|
keyFeatures: string[];
|
||||||
|
gallery: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Category {
|
||||||
|
[key: string]: string;
|
||||||
|
fullName: string;
|
||||||
|
shortName: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectTech {
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user