Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
f06cae217f | |||
55676a9896 | |||
cc118006ba | |||
|
49b28ffbc6 | ||
|
535c2550b0 | ||
|
2190b10090 | ||
|
77ef7532ee | ||
|
7d174ab051 | ||
|
4dd6a09b3f | ||
a530816cd6 | |||
|
d03832c2d1 |
12 changed files with 242 additions and 14 deletions
|
@ -22,6 +22,10 @@ FROM nginx:alpine
|
|||
# Copy the built application from the previous stage
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
|
||||
COPY dotechbro_nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
|
|
9
dotechbro_nginx.conf
Normal file
9
dotechbro_nginx.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html =404;
|
||||
}
|
||||
}
|
|
@ -14,5 +14,10 @@
|
|||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
<script
|
||||
defer
|
||||
src="https://unami.smigz.com/script.js"
|
||||
data-website-id="e07c8f76-9786-4201-a47a-482fd9d485a9"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
52
nginx.conf
Normal file
52
nginx.conf
Normal file
|
@ -0,0 +1,52 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for" - "$http_cf_connecting_ip"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
server_tokens off;
|
||||
|
||||
#gzip on;
|
||||
|
||||
# CloudFlare Ips
|
||||
real_ip_header CF-Connecting-IP;
|
||||
set_real_ip_from 173.245.48.0/20;
|
||||
set_real_ip_from 103.21.244.0/22;
|
||||
set_real_ip_from 103.22.200.0/22;
|
||||
set_real_ip_from 103.31.4.0/22;
|
||||
set_real_ip_from 141.101.64.0/18;
|
||||
set_real_ip_from 108.162.192.0/18;
|
||||
set_real_ip_from 190.93.240.0/20;
|
||||
set_real_ip_from 188.114.96.0/20;
|
||||
set_real_ip_from 197.234.240.0/22;
|
||||
set_real_ip_from 198.41.128.0/17;
|
||||
set_real_ip_from 162.158.0.0/15;
|
||||
set_real_ip_from 104.16.0.0/13;
|
||||
set_real_ip_from 104.24.0.0/14;
|
||||
set_real_ip_from 172.64.0.0/13;
|
||||
set_real_ip_from 131.0.72.0/22;
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
}
|
|
@ -4,8 +4,10 @@ import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
|
|||
import Header from './components/Header';
|
||||
import Footer from './components/Footer';
|
||||
import Home from './components/Home';
|
||||
import NotFound from './components/NotFound';
|
||||
import About from './components/About';
|
||||
import Roadmap from './components/Roadmap';
|
||||
import RoadmapDetail from './components/RoadmapDetail'; // Import the RoadmapDetail component
|
||||
|
||||
const App = () => {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
@ -21,7 +23,10 @@ const App = () => {
|
|||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/about" element={<About />} />
|
||||
<Route path="/roadmap" element={<Roadmap />} />
|
||||
<Route path="/roadmap" element={<Roadmap />}>
|
||||
<Route path=":id" element={<RoadmapDetail />} />
|
||||
</Route>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
Before Width: | Height: | Size: 4 KiB |
39
src/challenges.js
Normal file
39
src/challenges.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const challenges = [
|
||||
{
|
||||
title: 'Lack of Representation',
|
||||
content: 'The tech industry often lacks visible role models from similar backgrounds, which can deter individuals from pursuing careers in this field.',
|
||||
solution: 'Mentorship Programs: Seek out mentorship opportunities with experienced professionals who understand your journey and can offer guidance, support, and valuable networking connections.',
|
||||
},
|
||||
{
|
||||
title: 'Implicit Bias and Discrimination',
|
||||
content: 'Unconscious biases and systemic discrimination can create barriers to entry and advancement for minorities in tech.',
|
||||
solution: 'Empower Yourself: Develop strategies to counteract bias, such as documenting your achievements and seeking inclusive workplaces that prioritize diversity.',
|
||||
},
|
||||
{
|
||||
title: 'Limited Access to Education and Resources',
|
||||
content: 'Many underserved communities lack adequate exposure to technology and programming education, which can limit opportunities for entry into the tech field.',
|
||||
solution: 'Educational Initiatives: Take advantage of free or affordable coding bootcamps, online courses, and community workshops that focus on tech skills.',
|
||||
},
|
||||
{
|
||||
title: 'Financial Barriers',
|
||||
content: 'The high costs of education, certification programs, and living expenses can pose significant challenges.',
|
||||
solution: 'Scholarship and Grant Research: Look for scholarships and grants specifically aimed at minorities in tech. Building a strong portfolio can also demonstrate your skills to potential employers, making you a more competitive candidate.',
|
||||
},
|
||||
{
|
||||
title: 'Impostor Syndrome',
|
||||
content: 'Many individuals feel inadequate or fear being exposed as a fraud, which can hinder confidence and career advancement.',
|
||||
solution: 'Build Confidence: Share your experiences with peers or mentors, and focus on celebrating your achievements, no matter how small. Joining support groups can also be beneficial.',
|
||||
},
|
||||
{
|
||||
title: 'Networking Challenges',
|
||||
content: 'Establishing connections within the tech community can feel daunting, especially for newcomers. However, strong professional relationships are essential for mentorship and job opportunities.',
|
||||
solution: 'Engage in Networking Events: Actively participate in tech meetups, industry conferences, and hackathons. These events are excellent for learning and for building connections with others who share your passion.',
|
||||
},
|
||||
{
|
||||
title: 'Work-Life Balance',
|
||||
content: 'Balancing the demands of a tech career with personal and family responsibilities can be challenging, impacting overall well-being.',
|
||||
solution: 'Prioritize Self-Care: Establish routines that include time for rest and personal interests. Engaging in hobbies, exercise, and family time can enhance your mental health and productivity in your tech career.',
|
||||
},
|
||||
];
|
||||
|
||||
export default challenges;
|
34
src/components/Accordion.jsx
Normal file
34
src/components/Accordion.jsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
const Accordion = ({ items }) => {
|
||||
const [openIndex, setOpenIndex] = useState(null);
|
||||
|
||||
const toggleItem = (index) => {
|
||||
setOpenIndex(openIndex === index ? null : index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full bg-white p-8 rounded-lg shadow-lg mb-16">
|
||||
<h3 className="text-2xl font-semibold text-center mb-4 text-gray-900">Conquering Challenges: Practical Tips for Diverse Talent</h3>
|
||||
{items.map((item, index) => (
|
||||
<div key={index} className="mb-4">
|
||||
<button
|
||||
onClick={() => toggleItem(index)}
|
||||
className="w-full text-left text-lg font-semibold text-gray-800 bg-gray-100 p-4 rounded-lg shadow-md hover:bg-gray-300 transition duration-300"
|
||||
>
|
||||
{item.title}
|
||||
</button>
|
||||
{openIndex === index && (
|
||||
<div className="mt-2 p-4 bg-gray-200 rounded-lg shadow-inner">
|
||||
<p className="text-gray-700">{item.content}</p>
|
||||
<p className="mt-2 text-gray-700 font-semibold">Solution:</p>
|
||||
<p className="text-gray-700">{item.solution}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Accordion;
|
|
@ -68,6 +68,7 @@ const Home = () => {
|
|||
<button
|
||||
className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300"
|
||||
onClick={handleDialogOpen}
|
||||
data-umami-event="Start Today Button"
|
||||
>
|
||||
Start Today
|
||||
</button>
|
||||
|
@ -108,6 +109,7 @@ const Home = () => {
|
|||
<button
|
||||
onClick={handleDialogOpen}
|
||||
className="mt-8 px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300"
|
||||
data-umami-event="Join Now Button"
|
||||
>
|
||||
Join Now
|
||||
</button>
|
||||
|
@ -120,4 +122,3 @@ const Home = () => {
|
|||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
|
|
15
src/components/NotFound.jsx
Normal file
15
src/components/NotFound.jsx
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
const NotFound = () => {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
||||
<h1 className="text-6xl font-bold text-gray-900 mb-8">404</h1>
|
||||
<p className="text-lg text-gray-700 mb-8">Oops! The page you're looking for doesn't exist.</p>
|
||||
<Link to="/" className="px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300">
|
||||
Go Back Home
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFound;
|
|
@ -1,12 +1,61 @@
|
|||
const Roadmap = () => (
|
||||
<div className="p-8 flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
||||
<h2 className="text-4xl font-bold text-center leading-tight">
|
||||
import { Outlet, useLocation, Link } from 'react-router-dom';
|
||||
import challenges from '../challenges';
|
||||
import roadmaps from '../roadmaps.json'; // Import the roadmaps data
|
||||
import Accordion from './Accordion'; // Import the Accordion component
|
||||
|
||||
const Roadmap = () => {
|
||||
const location = useLocation();
|
||||
const isRootPath = location.pathname === '/roadmap';
|
||||
|
||||
return (
|
||||
<div className="p-8 flex flex-col items-center justify-center min-h-screen bg-gray-100 overflow-x-hidden">
|
||||
<h2 className="text-4xl font-bold text-center leading-tight text-gray-900 mb-8">
|
||||
Roadmaps
|
||||
</h2>
|
||||
<p className="mt-4 text-lg text-center max-w-2xl">
|
||||
Explore our detailed roadmaps to guide your journey into the tech industry.
|
||||
<p className="text-lg text-center max-w-2xl text-gray-700 mb-16">
|
||||
Dive into our comprehensive roadmaps designed to illuminate your path into the tech industry. Each roadmap offers step-by-step guidance, tailored resources, and practical tips to help you navigate challenges and seize opportunities. Whether you’re just starting out or looking to advance your career, these roadmaps are your essential tools for success. Let’s chart your course together!
|
||||
</p>
|
||||
|
||||
{isRootPath && (
|
||||
<>
|
||||
<Accordion items={challenges} />
|
||||
|
||||
<div className="w-screen bg-gray-900 text-white py-16 mb-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h3 className="text-2xl font-semibold text-center mb-4">Available Roadmaps</h3>
|
||||
<div className="flex flex-col md:flex-row justify-center items-stretch space-y-8 md:space-y-0 md:space-x-8">
|
||||
{roadmaps.map((roadmap, index) => (
|
||||
<Link key={index} to={`/roadmap/${roadmap.id}`} className="bg-white text-gray-900 p-8 rounded-lg shadow-lg w-full md:w-1/3 text-center transform transition-transform hover:scale-105 flex flex-col">
|
||||
<h3 className="text-2xl font-semibold">{roadmap.title}</h3>
|
||||
<p className="mt-4 flex-grow">{roadmap.description}</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full bg-gray-50 p-8 rounded-lg shadow-lg mb-16">
|
||||
<h3 className="text-2xl font-semibold text-center mb-4 text-gray-900">More Roadmaps Coming Soon</h3>
|
||||
<p className="text-lg text-gray-700">
|
||||
We’re excited to share that we’re actively developing additional roadmaps to guide you on your tech journey. These resources are designed to empower you, providing clear paths and actionable steps tailored to your goals. Keep an eye out for updates—your future in tech is bright, and we’re here to support you every step of the way!
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
<div className="w-full bg-white p-8 rounded-lg shadow-lg text-center">
|
||||
<h3 className="text-2xl font-semibold mb-4 text-gray-900">Open Source Collaboration</h3>
|
||||
<p className="text-lg text-gray-700 mb-8">
|
||||
These roadmaps are open source and we welcome collaboration from the community. Feel free to contribute and help us improve these resources.
|
||||
</p>
|
||||
<button className="px-6 py-3 bg-green-600 text-white text-lg font-semibold rounded hover:bg-green-700 transition duration-300">
|
||||
Contribute Now
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!isRootPath && <Outlet />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Roadmap;
|
16
src/components/RoadmapDetail.jsx
Normal file
16
src/components/RoadmapDetail.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
// src/components/RoadmapDetail.jsx
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
const RoadmapDetail = () => {
|
||||
const { id } = useParams();
|
||||
|
||||
return (
|
||||
<div className="p-8">
|
||||
<h2 className="text-4xl font-bold text-center mb-8">Roadmap Detail: {id}</h2>
|
||||
<p className="text-lg text-center">Details for roadmap {id} will be displayed here.</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoadmapDetail;
|
Loading…
Reference in a new issue