Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
64d33253cc | |||
2b2679b363 | |||
d364b3c3ad |
23 changed files with 347 additions and 1725 deletions
45
.gitea/workflows/pipeline-test.yml
Normal file
45
.gitea/workflows/pipeline-test.yml
Normal file
|
@ -0,0 +1,45 @@
|
|||
name: Build and Deploy Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- ci-build
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
steps:
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Red Hat Registry
|
||||
uses: https://github.com/redhat-actions/podman-login@v1
|
||||
with:
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
registry: git.thecodedom.com
|
||||
|
||||
|
||||
- name: Buildah Action
|
||||
uses: https://github.com/redhat-actions/buildah-build@v2
|
||||
with:
|
||||
image: my-new-image
|
||||
tags: test
|
||||
containerfiles: |
|
||||
./Dockerfile
|
||||
|
||||
# - name: Set up Docker Buildx
|
||||
# uses: docker/setup-buildx-action@v2
|
||||
#
|
||||
# - name: Log in to Gitea Container Registry
|
||||
# uses: docker/login-action@v3
|
||||
# with:
|
||||
#
|
||||
# - name: Build and push Docker image
|
||||
# uses: docker/build-push-action@v6
|
||||
# with:
|
||||
# context: .
|
||||
# push: true
|
||||
# tags: git.thecodedom.com/dotechbro/dotechbro-website:latest
|
||||
|
26
CLAUDE.md
26
CLAUDE.md
|
@ -1,26 +0,0 @@
|
|||
# Development Guide
|
||||
|
||||
## Commands
|
||||
- **Start dev server**: `npm run dev`
|
||||
- **Build for production**: `npm run build`
|
||||
- **Lint code**: `npm run lint`
|
||||
- **Preview production build**: `npm run preview`
|
||||
|
||||
## Code Style Guidelines
|
||||
- **React Components**: Use functional components with hooks
|
||||
- **Imports**: Group imports by: React/libraries, components, styles/assets
|
||||
- **Formatting**: Use 2-space indentation, semicolons, single quotes
|
||||
- **Naming**:
|
||||
- Components: PascalCase (e.g., `Header.jsx`)
|
||||
- Functions/variables: camelCase
|
||||
- Files: Component files use .jsx extension
|
||||
- **CSS**: Use Tailwind utility classes with component-specific CSS when needed
|
||||
- **Error Handling**: Use try/catch blocks and provide user-friendly error messages
|
||||
- **Props**: Use destructuring for component props
|
||||
- **State Management**: Use React hooks (useState, useEffect) for component state
|
||||
|
||||
## Tech Stack
|
||||
- React 18 w/ functional components
|
||||
- React Router for navigation
|
||||
- Tailwind CSS for styling
|
||||
- Vite for build tool
|
|
@ -22,10 +22,6 @@ 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
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
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,10 +14,5 @@
|
|||
<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
52
nginx.conf
|
@ -1,52 +0,0 @@
|
|||
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,10 +4,8 @@ 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);
|
||||
|
@ -23,10 +21,7 @@ const App = () => {
|
|||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/about" element={<About />} />
|
||||
<Route path="/roadmap" element={<Roadmap />}>
|
||||
<Route path=":id" element={<RoadmapDetail />} />
|
||||
</Route>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
<Route path="/roadmap" element={<Roadmap />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
|
|
1
src/assets/react.svg
Normal file
1
src/assets/react.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<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>
|
After Width: | Height: | Size: 4 KiB |
|
@ -1,39 +0,0 @@
|
|||
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;
|
|
@ -1,168 +1,12 @@
|
|||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const About = () => {
|
||||
return (
|
||||
<div className="bg-dark-900 text-white">
|
||||
{/* Hero Section */}
|
||||
<section className="py-20 bg-gradient-to-b from-dark-800 to-dark-900">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="text-center max-w-3xl mx-auto">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-6">Our Mission</h1>
|
||||
<p className="text-xl text-gray-300 leading-relaxed mb-8">
|
||||
DoTechBro is dedicated to empowering minorities, particularly African Americans, to
|
||||
successfully transition into the tech industry and thrive in their careers.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Vision Section */}
|
||||
<section className="py-16 bg-dark-800">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold mb-6 bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent">Our Vision</h2>
|
||||
<p className="text-gray-300 mb-6 leading-relaxed">
|
||||
We envision a tech industry that reflects the diversity of our society, where
|
||||
minorities have equal opportunities to innovate, lead, and succeed. Our goal is to
|
||||
bridge the gap by providing targeted resources, mentorship, and community support.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
By creating comprehensive roadmaps, curating high-quality learning materials, and
|
||||
fostering a supportive community, we aim to give underrepresented individuals the
|
||||
confidence and skills needed to thrive in technology careers.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-dark-700 p-8 rounded-xl shadow-lg">
|
||||
<h3 className="text-2xl font-bold mb-4">Why We Started</h3>
|
||||
<p className="text-gray-300 mb-4">
|
||||
The tech industry has a well-documented diversity problem. Despite making up 13.4% of the
|
||||
U.S. population, Black Americans represent only about 7% of the computing workforce.
|
||||
We believe this isn't due to lack of talent or interest, but rather barriers to entry and lack of tailored resources.
|
||||
</p>
|
||||
<p className="text-gray-300">
|
||||
DoTechBro was created to address these challenges head-on by providing clear pathways
|
||||
into tech that acknowledge and overcome the unique obstacles minorities face.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* What We Do Section */}
|
||||
<section className="py-16 bg-gradient-to-b from-dark-900 to-dark-800">
|
||||
<div className="container mx-auto px-6">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">What We Do</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="bg-dark-700 rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow duration-300">
|
||||
<div className="text-primary-500 text-3xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3">Career Roadmaps</h3>
|
||||
<p className="text-gray-300">
|
||||
We create tailored roadmaps for various tech career paths, breaking down complex journeys into manageable steps with
|
||||
clear guidance and resources for each stage.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow duration-300">
|
||||
<div className="text-primary-500 text-3xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3">Resource Curation</h3>
|
||||
<p className="text-gray-300">
|
||||
We curate high-quality learning resources, from tutorials to practice projects, saving you time and helping you
|
||||
focus on what actually works to build your skills.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 rounded-xl p-8 shadow-lg hover:shadow-xl transition-shadow duration-300">
|
||||
<div className="text-primary-500 text-3xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-3">Community Building</h3>
|
||||
<p className="text-gray-300">
|
||||
We're building a supportive community where you can connect with others on similar journeys,
|
||||
share experiences, and get guidance from those who've succeeded.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Values */}
|
||||
<section className="py-16 bg-dark-800">
|
||||
<div className="container mx-auto px-6">
|
||||
<h2 className="text-3xl font-bold text-center mb-6">Our Values</h2>
|
||||
<p className="text-center text-gray-300 max-w-3xl mx-auto mb-12">
|
||||
These core principles guide everything we do at DoTechBro and shape how we serve our community.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="bg-dark-700 rounded-lg p-6 border-l-4 border-primary-500">
|
||||
<h3 className="text-xl font-bold mb-2">Accessibility</h3>
|
||||
<p className="text-gray-300">
|
||||
We believe tech education should be accessible to everyone, regardless of background or prior experience.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 rounded-lg p-6 border-l-4 border-primary-500">
|
||||
<h3 className="text-xl font-bold mb-2">Authenticity</h3>
|
||||
<p className="text-gray-300">
|
||||
We keep it real about the challenges of breaking into tech while providing actionable solutions.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 rounded-lg p-6 border-l-4 border-primary-500">
|
||||
<h3 className="text-xl font-bold mb-2">Community</h3>
|
||||
<p className="text-gray-300">
|
||||
We believe in the power of community to overcome obstacles and accelerate growth.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 rounded-lg p-6 border-l-4 border-primary-500">
|
||||
<h3 className="text-xl font-bold mb-2">Excellence</h3>
|
||||
<p className="text-gray-300">
|
||||
We're committed to providing high-quality resources that actually prepare you for success in the industry.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Call to Action */}
|
||||
<section className="py-20 bg-gradient-to-b from-dark-800 to-dark-900">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h2 className="text-3xl font-bold mb-6">Ready to Start Your Tech Journey?</h2>
|
||||
<p className="text-xl text-gray-300 mb-8 max-w-2xl mx-auto">
|
||||
Join our community today and take the first step toward your career in tech.
|
||||
</p>
|
||||
<div className="flex flex-wrap justify-center gap-4">
|
||||
<Link
|
||||
to="/roadmap"
|
||||
className="px-8 py-3 bg-primary-600 hover:bg-primary-700 text-white rounded-lg shadow-lg transition-colors"
|
||||
>
|
||||
Explore Roadmaps
|
||||
</Link>
|
||||
<Link
|
||||
to="/"
|
||||
className="px-8 py-3 border-2 border-primary-500 text-primary-400 hover:bg-primary-500/10 rounded-lg transition-colors"
|
||||
>
|
||||
Join Our Community
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const About = () => (
|
||||
<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">
|
||||
About Us
|
||||
</h2>
|
||||
<p className="mt-2 text-xs text-center text-gray-600">
|
||||
Do Tech Bro is dedicated to helping minorities, mainly African Americans, pivot into the tech field.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default About;
|
|
@ -1,75 +0,0 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
const Accordion = ({ items }) => {
|
||||
const [openIndex, setOpenIndex] = useState(0); // Start with first item open
|
||||
|
||||
const toggleItem = (index) => {
|
||||
setOpenIndex(openIndex === index ? null : index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`mb-4 border border-dark-600 rounded-lg overflow-hidden transition-all duration-300 ${
|
||||
openIndex === index ? 'shadow-lg' : 'shadow'
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
onClick={() => toggleItem(index)}
|
||||
className={`w-full flex items-center justify-between text-left p-5 font-medium transition-colors ${
|
||||
openIndex === index
|
||||
? 'bg-dark-700 text-white'
|
||||
: 'bg-dark-800 text-gray-300 hover:bg-dark-700'
|
||||
}`}
|
||||
aria-expanded={openIndex === index}
|
||||
>
|
||||
<span className="text-lg">{item.title}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={`h-5 w-5 transition-transform duration-300 ${openIndex === index ? 'transform rotate-180' : ''}`}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div
|
||||
className={`overflow-hidden transition-all duration-300 ease-in-out ${
|
||||
openIndex === index ? 'max-h-96' : 'max-h-0'
|
||||
}`}
|
||||
>
|
||||
<div className="p-5 bg-dark-700 border-t border-dark-600">
|
||||
<p className="text-gray-300 mb-4">{item.content}</p>
|
||||
|
||||
<div className="mt-4 border-l-4 border-primary-500 pl-4">
|
||||
<p className="text-primary-400 font-semibold mb-2">Our Solution:</p>
|
||||
<p className="text-gray-300">{item.solution}</p>
|
||||
</div>
|
||||
|
||||
{item.resources && (
|
||||
<div className="mt-4 pt-4 border-t border-dark-600">
|
||||
<p className="text-white font-medium mb-2">Helpful Resources:</p>
|
||||
<ul className="list-disc list-inside text-primary-400 space-y-1">
|
||||
{item.resources.map((resource, i) => (
|
||||
<li key={i}>
|
||||
<a href={resource.url} className="hover:text-primary-300 transition-colors" target="_blank" rel="noopener noreferrer">
|
||||
{resource.title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Accordion;
|
|
@ -3,75 +3,24 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||
import { faServer, faProjectDiagram, faCode } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const icons = {
|
||||
"devops-sre": faServer,
|
||||
"non-technical-tech": faProjectDiagram,
|
||||
"development": faCode
|
||||
"devops-sre": faServer,
|
||||
"non-technical-tech": faProjectDiagram,
|
||||
"development": faCode
|
||||
};
|
||||
|
||||
const FeaturedRoadmaps = ({ roadmaps }) => (
|
||||
<div className="container mx-auto px-6 py-12">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">Featured Roadmaps</h2>
|
||||
<p className="text-lg text-gray-300 max-w-2xl mx-auto">
|
||||
Choose your tech path and follow our step-by-step guidance to build your career
|
||||
</p>
|
||||
<div className="p-8">
|
||||
<h2 className="text-4xl font-bold text-center mb-8">Featured Roadmaps</h2>
|
||||
<div className="flex flex-col md:flex-row justify-center items-center 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">
|
||||
<FontAwesomeIcon icon={icons[roadmap.id]} className="text-green-600 text-4xl mb-4" />
|
||||
<h3 className="text-2xl font-semibold">{roadmap.title}</h3>
|
||||
<p className="mt-4">{roadmap.description}</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{roadmaps.map((roadmap, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
to={`/roadmap/${roadmap.id}`}
|
||||
className="feature-card bg-dark-700 rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-all duration-300"
|
||||
>
|
||||
<div className="p-1 bg-gradient-to-r from-primary-500 to-secondary-500">
|
||||
<div className="bg-dark-700 p-8 rounded-t-xl">
|
||||
<div className="flex justify-center items-center w-16 h-16 mx-auto mb-6 rounded-full bg-dark-800 text-primary-500">
|
||||
<FontAwesomeIcon icon={icons[roadmap.id]} className="text-3xl" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold text-center mb-3">{roadmap.title}</h3>
|
||||
<p className="text-gray-400 text-center mb-4">{roadmap.description}</p>
|
||||
<div className="mt-6 flex justify-center">
|
||||
<span className="inline-flex items-center text-primary-400 font-medium">
|
||||
Explore roadmap
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-1" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-8 py-4 bg-dark-600 text-center">
|
||||
<div className="flex justify-center space-x-2">
|
||||
{['Beginner', 'Intermediate', 'Advanced'].map((level, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={`text-xs px-2 py-1 rounded-full ${
|
||||
i === 0 ? 'bg-primary-500/20 text-primary-300' :
|
||||
'bg-dark-500 text-gray-400'
|
||||
}`}
|
||||
>
|
||||
{level}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-12 text-center">
|
||||
<Link
|
||||
to="/roadmap"
|
||||
className="inline-flex items-center px-6 py-3 bg-dark-700 hover:bg-dark-600 text-white font-medium rounded-lg transition-colors duration-300"
|
||||
>
|
||||
View All Roadmaps
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default FeaturedRoadmaps;
|
|
@ -1,95 +1,10 @@
|
|||
// src/components/Footer.jsx
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const Footer = () => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<footer className="bg-dark-900 text-white py-12">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
||||
{/* Logo and About */}
|
||||
<div className="col-span-1 md:col-span-1">
|
||||
<Link
|
||||
to="/"
|
||||
className="text-2xl font-bold bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent mb-4 block"
|
||||
>
|
||||
DoTechBro.org
|
||||
</Link>
|
||||
<p className="text-gray-400 mt-4">
|
||||
Empowering minorities to succeed in tech through community support and targeted resources.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div className="col-span-1">
|
||||
<h3 className="text-lg font-bold mb-4 text-white">Quick Links</h3>
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<Link to="/" className="text-gray-400 hover:text-primary-400 transition-colors">Home</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/about" className="text-gray-400 hover:text-primary-400 transition-colors">About</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/roadmap" className="text-gray-400 hover:text-primary-400 transition-colors">Roadmaps</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Roadmaps */}
|
||||
<div className="col-span-1">
|
||||
<h3 className="text-lg font-bold mb-4 text-white">Popular Roadmaps</h3>
|
||||
<ul className="space-y-2">
|
||||
<li>
|
||||
<Link to="/roadmap" className="text-gray-400 hover:text-primary-400 transition-colors">Web Development</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/roadmap" className="text-gray-400 hover:text-primary-400 transition-colors">Data Science</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/roadmap" className="text-gray-400 hover:text-primary-400 transition-colors">UI/UX Design</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Get in Touch */}
|
||||
<div className="col-span-1">
|
||||
<h3 className="text-lg font-bold mb-4 text-white">Get in Touch</h3>
|
||||
<div className="flex space-x-4 mt-4">
|
||||
<a href="#" className="text-gray-400 hover:text-primary-400 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" className="text-gray-400 hover:text-primary-400 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" className="text-gray-400 hover:text-primary-400 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" className="text-gray-400 hover:text-primary-400 transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-gray-800 mt-8 pt-8 text-center">
|
||||
<p className="text-gray-400">
|
||||
© {currentYear} DoTechBro.org. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
const Footer = () => (
|
||||
<footer className="bg-gray-800 text-white p-4 text-center">
|
||||
<p>© {new Date().getFullYear()} Do Tech Bro. All rights reserved.</p>
|
||||
</footer>
|
||||
);
|
||||
|
||||
export default Footer;
|
|
@ -1,50 +1,50 @@
|
|||
/* src/components/Header.css */
|
||||
.link-underline {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-weight: 500;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
|
||||
.link-underline::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: var(--color-primary);
|
||||
transform: scaleX(0);
|
||||
transform-origin: bottom right;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.link-underline:hover::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes dropdown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
/* src/components/Header.css */
|
||||
.link-underline {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
|
||||
.link-underline::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
background-color: #38a169;
|
||||
/* Darker green color */
|
||||
transform: scaleX(0);
|
||||
transform-origin: bottom right;
|
||||
transition: transform 0.3s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-dropdown {
|
||||
animation: dropdown 0.3s ease;
|
||||
}
|
||||
.link-underline:hover::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
/* Responsive layout adjustments */
|
||||
.page-content {
|
||||
transition: margin-top 0.3s ease;
|
||||
}
|
||||
/* Header.css */
|
||||
@keyframes dropdown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.page-content.dropdown-active {
|
||||
margin-top: 12rem;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-dropdown {
|
||||
animation: dropdown 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
transition: margin-top 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.page-content.dropdown-active {
|
||||
margin-top: 150px;
|
||||
/* Adjust based on the height of the dropdown menu */
|
||||
}
|
|
@ -7,48 +7,31 @@ const Header = ({ onMenuToggle }) => {
|
|||
|
||||
const toggleMenu = () => {
|
||||
setIsOpen(!isOpen);
|
||||
if (onMenuToggle) onMenuToggle(!isOpen);
|
||||
onMenuToggle(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="bg-dark-800 text-white py-4 px-6 flex justify-between items-center relative shadow-md">
|
||||
<div className="flex items-center">
|
||||
<Link
|
||||
to="/"
|
||||
className="text-2xl font-bold bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent hover:opacity-90 transition-opacity duration-300"
|
||||
>
|
||||
DoTechBro.org
|
||||
</Link>
|
||||
<header className="bg-gray-900 text-white p-4 flex justify-between items-center relative">
|
||||
<div className="text-2xl font-bold">
|
||||
<Link to="/" className="relative">DoTechBro.org</Link>
|
||||
</div>
|
||||
|
||||
<div className="md:hidden">
|
||||
<button
|
||||
onClick={toggleMenu}
|
||||
className="p-2 rounded-md hover:bg-dark-700 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors"
|
||||
aria-label={isOpen ? "Close menu" : "Open menu"}
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
<button onClick={toggleMenu} className="focus:outline-none">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d={isOpen ? "M6 18L18 6M6 6l12 12" : "M4 6h16M4 12h16m-7 6h7"}></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav className="hidden md:flex md:items-center md:space-x-8">
|
||||
<Link to="/" className="link-underline text-white hover:text-primary-400 transition-colors">Home</Link>
|
||||
<Link to="/about" className="link-underline text-white hover:text-primary-400 transition-colors">About</Link>
|
||||
<Link to="/roadmap" className="link-underline text-white hover:text-primary-400 transition-colors">Roadmaps</Link>
|
||||
<Link to="/roadmap" className="ml-4 bg-primary-600 hover:bg-primary-700 text-white py-2 px-4 rounded-lg transition-colors shadow-sm">Get Started</Link>
|
||||
<nav className="hidden md:flex md:space-x-4">
|
||||
<Link to="/" className="link-underline">Home</Link>
|
||||
<Link to="/about" className="link-underline">About</Link>
|
||||
<Link to="/roadmap" className="link-underline">Roadmaps</Link>
|
||||
</nav>
|
||||
|
||||
{isOpen && (
|
||||
<div className="absolute top-full left-0 w-full bg-dark-800 text-white shadow-lg rounded-b-lg z-50 md:hidden animate-dropdown">
|
||||
<div className="flex flex-col py-3 px-6 space-y-4">
|
||||
<Link to="/" className="py-2 link-underline text-white hover:text-primary-400 transition-colors" onClick={toggleMenu}>Home</Link>
|
||||
<Link to="/about" className="py-2 link-underline text-white hover:text-primary-400 transition-colors" onClick={toggleMenu}>About</Link>
|
||||
<Link to="/roadmap" className="py-2 link-underline text-white hover:text-primary-400 transition-colors" onClick={toggleMenu}>Roadmaps</Link>
|
||||
<Link to="/roadmap" className="bg-primary-600 hover:bg-primary-700 text-white py-2 px-4 rounded-lg text-center transition-colors shadow-sm" onClick={toggleMenu}>Get Started</Link>
|
||||
</div>
|
||||
<div className="absolute top-full left-0 w-full bg-gray-900 text-white flex flex-col items-center md:hidden animate-dropdown">
|
||||
<Link to="/" className="block py-2 link-underline" onClick={toggleMenu}>Home</Link>
|
||||
<Link to="/about" className="block py-2 link-underline" onClick={toggleMenu}>About</Link>
|
||||
<Link to="/roadmap" className="block py-2 link-underline" onClick={toggleMenu}>Roadmaps</Link>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
|
|
@ -1,60 +1,23 @@
|
|||
/* Home.css */
|
||||
.page-content {
|
||||
transition: margin-top 0.3s ease;
|
||||
transition: margin-top 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.page-content.dropdown-active {
|
||||
margin-top: 12rem;
|
||||
margin-top: 150px;
|
||||
/* Adjust based on the height of the dropdown menu */
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.8s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Gradient text effect for headings */
|
||||
.gradient-text {
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
background-image: linear-gradient(to right, var(--color-primary), var(--color-secondary));
|
||||
}
|
||||
|
||||
/* Hover effects for cards */
|
||||
.feature-card {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Button hover effects */
|
||||
.hover-scale {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-scale:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Image effects */
|
||||
.image-hover {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.image-hover:hover {
|
||||
transform: rotate(2deg) scale(1.02);
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3);
|
||||
animation: fadeIn 1s ease-in-out forwards;
|
||||
}
|
|
@ -1,202 +1,123 @@
|
|||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import FeaturedRoadmaps from "./FeaturedRoadmaps";
|
||||
import MailingListDialog from "./MailingListDialog";
|
||||
import roadmaps from "../roadmaps.json";
|
||||
import "./Home.css"; // Import the custom CSS file
|
||||
|
||||
const Home = () => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const sectionsRef = useRef([]);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("animate-fade-in");
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1 },
|
||||
);
|
||||
|
||||
sectionsRef.current.forEach((section) => {
|
||||
if (section) {
|
||||
observer.observe(section);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
sectionsRef.current.forEach((section) => {
|
||||
if (section) {
|
||||
observer.unobserve(section);
|
||||
}
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleDialogOpen = () => {
|
||||
setDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleDialogClose = () => {
|
||||
setDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleMenuToggle = (isOpen) => {
|
||||
setMenuOpen(isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`page-content ${menuOpen ? "dropdown-active" : ""}`}>
|
||||
{/* Hero Section */}
|
||||
<section
|
||||
className="w-full py-16 md:py-24 bg-gradient-to-b from-dark-900 to-dark-800 text-white opacity-0"
|
||||
ref={(el) => (sectionsRef.current[0] = el)}
|
||||
>
|
||||
<div className="container mx-auto px-6 flex flex-col md:flex-row items-center justify-between gap-12">
|
||||
<div className="md:w-1/2 flex flex-col items-start">
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight mb-4">
|
||||
Pivot into <span className="text-primary-500">tech</span>
|
||||
<br />
|
||||
<span className="font-medium text-3xl md:text-4xl lg:text-5xl">with a head start</span>
|
||||
</h1>
|
||||
<p className="text-lg text-gray-300 mb-8 max-w-lg">
|
||||
Empowering minorities to overcome barriers and succeed in the tech
|
||||
industry with confidence and community support.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<button
|
||||
className="px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-medium rounded-lg shadow-lg transition-colors duration-300 transform hover:scale-105"
|
||||
onClick={handleDialogOpen}
|
||||
data-umami-event="Start Today Button"
|
||||
>
|
||||
Start Your Journey
|
||||
</button>
|
||||
<Link
|
||||
to="/roadmap"
|
||||
className="px-6 py-3 bg-transparent border-2 border-primary-500 text-primary-400 font-medium rounded-lg hover:bg-primary-500/10 transition-colors duration-300"
|
||||
>
|
||||
Explore Roadmaps
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 md:mt-0 md:w-1/2 flex justify-center">
|
||||
<img
|
||||
src="/hero-logo.png"
|
||||
alt="Tech illustration"
|
||||
className="w-full max-w-md rounded-lg shadow-2xl transform hover:rotate-1 transition-transform duration-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Section */}
|
||||
<section
|
||||
className="w-full py-16 bg-dark-800 text-white opacity-0"
|
||||
ref={(el) => (sectionsRef.current[1] = el)}
|
||||
>
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">Why Choose Our Roadmaps</h2>
|
||||
<p className="text-lg text-gray-300 max-w-2xl mx-auto">
|
||||
Our carefully designed roadmaps will guide you through your tech journey with clear steps and resources.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="bg-dark-700 p-8 rounded-xl shadow-lg hover:shadow-xl transition-shadow">
|
||||
<div className="text-primary-500 text-4xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold mb-2">Curated Resources</h3>
|
||||
<p className="text-gray-300">
|
||||
Hand-picked learning resources tested and approved by industry professionals.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 p-8 rounded-xl shadow-lg hover:shadow-xl transition-shadow">
|
||||
<div className="text-primary-500 text-4xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold mb-2">Community Support</h3>
|
||||
<p className="text-gray-300">
|
||||
Join a community of like-minded individuals on similar journeys.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-dark-700 p-8 rounded-xl shadow-lg hover:shadow-xl transition-shadow">
|
||||
<div className="text-primary-500 text-4xl mb-4">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold mb-2">Clear Progression</h3>
|
||||
<p className="text-gray-300">
|
||||
Step-by-step guidance from basics to advanced topics with practical challenges.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Featured Roadmaps Section */}
|
||||
<section
|
||||
className="w-full py-16 bg-gradient-to-b from-dark-800 to-dark-700 text-white opacity-0"
|
||||
ref={(el) => (sectionsRef.current[2] = el)}
|
||||
>
|
||||
<FeaturedRoadmaps roadmaps={roadmaps} />
|
||||
</section>
|
||||
|
||||
{/* Testimonials (Coming Soon) */}
|
||||
<section
|
||||
className="w-full py-16 bg-dark-700 text-white opacity-0"
|
||||
ref={(el) => (sectionsRef.current[3] = el)}
|
||||
>
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-8">Success Stories</h2>
|
||||
<div className="bg-dark-600 p-8 rounded-xl shadow-lg max-w-2xl mx-auto">
|
||||
<p className="text-xl italic mb-6">
|
||||
"Testimonials from our successful community members coming soon... Join us and become one of our success stories!"
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<Link to="/about" className="text-primary-400 hover:text-primary-300 transition-colors font-medium">
|
||||
Learn more about our mission →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Call to Action */}
|
||||
<section
|
||||
className="w-full py-16 bg-gradient-to-b from-dark-700 to-dark-900 text-white opacity-0"
|
||||
ref={(el) => (sectionsRef.current[4] = el)}
|
||||
>
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">Ready to Start Your Tech Journey?</h2>
|
||||
<p className="text-lg text-gray-300 max-w-2xl mx-auto mb-8">
|
||||
Join our community today and get access to all our roadmaps, resources, and supportive network.
|
||||
</p>
|
||||
<button
|
||||
onClick={handleDialogOpen}
|
||||
className="px-8 py-4 bg-primary-600 hover:bg-primary-700 text-white text-lg font-medium rounded-lg shadow-lg transition-all duration-300 transform hover:scale-105"
|
||||
data-umami-event="Join Now Button"
|
||||
>
|
||||
Join Our Community
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<MailingListDialog open={dialogOpen} onClose={handleDialogClose} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import FeaturedRoadmaps from "./FeaturedRoadmaps";
|
||||
import MailingListDialog from "./MailingListDialog";
|
||||
import roadmaps from "../roadmaps.json";
|
||||
import "./Home.css"; // Import the custom CSS file
|
||||
|
||||
const Home = () => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const sectionsRef = useRef([]);
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("animate-fade-in");
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 0.1 },
|
||||
);
|
||||
|
||||
sectionsRef.current.forEach((section) => {
|
||||
if (section) {
|
||||
observer.observe(section);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
sectionsRef.current.forEach((section) => {
|
||||
if (section) {
|
||||
observer.unobserve(section);
|
||||
}
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleDialogOpen = () => {
|
||||
setDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleDialogClose = () => {
|
||||
setDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleMenuToggle = (isOpen) => {
|
||||
setMenuOpen(isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`page-content ${menuOpen ? "dropdown-active" : ""}`}>
|
||||
<div className="flex flex-col items-center justify-center w-full">
|
||||
<div
|
||||
className="w-full p-8 flex flex-col md:flex-row items-center justify-center min-h-screen bg-gray-100 opacity-0"
|
||||
ref={(el) => (sectionsRef.current[0] = el)}
|
||||
>
|
||||
<div className="md:w-1/2 flex flex-col items-center text-center">
|
||||
<h2 className="text-6xl font-bold leading-tight">
|
||||
Pivot into <span className="text-green-600">tech.</span>
|
||||
<br />
|
||||
<span className="font-semibold">with a head start</span>
|
||||
</h2>
|
||||
<p className="mt-4 text-lg max-w-2xl">
|
||||
Empowering minorities to overcome barriers and succeed in the tech
|
||||
industry with confidence.
|
||||
</p>
|
||||
<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}
|
||||
>
|
||||
Start Today
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-8 md:mt-0 md:w-1/2 flex justify-center">
|
||||
<img
|
||||
src="/hero-logo.png"
|
||||
alt="Tech illustration"
|
||||
className="w-full max-w-md rounded-lg shadow-lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="w-full bg-gray-900 text-white py-16 opacity-0"
|
||||
ref={(el) => (sectionsRef.current[1] = el)}
|
||||
>
|
||||
<FeaturedRoadmaps roadmaps={roadmaps} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="w-full p-8 bg-white text-center my-16 opacity-0"
|
||||
ref={(el) => (sectionsRef.current[2] = el)}
|
||||
>
|
||||
<h2 className="text-4xl font-bold mb-8">Testimonials</h2>
|
||||
<p className="text-lg">Coming soon...</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="w-full p-8 bg-gray-900 text-white text-center opacity-0"
|
||||
ref={(el) => (sectionsRef.current[3] = el)}
|
||||
>
|
||||
<h2 className="text-4xl font-bold mb-8">Join Our Community</h2>
|
||||
<p className="text-lg max-w-2xl mx-auto">
|
||||
Connect with like-minded individuals, share your journey, and get
|
||||
support from our community.
|
||||
</p>
|
||||
<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"
|
||||
>
|
||||
Join Now
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<MailingListDialog open={dialogOpen} onClose={handleDialogClose} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
|
|
|
@ -6,50 +6,6 @@ import DialogContentText from "@mui/material/DialogContentText";
|
|||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import Button from "@mui/material/Button";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
|
||||
// Create a custom theme that matches our design system
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#22c55e', // primary-600 color
|
||||
},
|
||||
secondary: {
|
||||
main: '#6366f1', // secondary-500 color
|
||||
},
|
||||
background: {
|
||||
default: '#0f172a', // dark-900 color
|
||||
paper: '#1e293b', // dark-800 color
|
||||
},
|
||||
text: {
|
||||
primary: '#f8fafc',
|
||||
secondary: '#94a3b8',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: 'Inter, system-ui, sans-serif',
|
||||
},
|
||||
shape: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
components: {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialog: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
borderRadius: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const MailingListDialog = ({ open, onClose }) => {
|
||||
const [name, setName] = useState("");
|
||||
|
@ -62,19 +18,6 @@ const MailingListDialog = ({ open, onClose }) => {
|
|||
setError("");
|
||||
setSuccess("");
|
||||
|
||||
// Basic validation
|
||||
if (!name.trim() || !email.trim()) {
|
||||
setError("Please fill in all fields");
|
||||
return;
|
||||
}
|
||||
|
||||
// Email validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
setError("Please enter a valid email address");
|
||||
return;
|
||||
}
|
||||
|
||||
const form = document.createElement("form");
|
||||
form.action = "https://tech.us9.list-manage.com/subscribe/post";
|
||||
form.method = "POST";
|
||||
|
@ -102,141 +45,63 @@ const MailingListDialog = ({ open, onClose }) => {
|
|||
setSuccess("Thank you for subscribing!");
|
||||
setName("");
|
||||
setEmail("");
|
||||
|
||||
// Close the dialog after a short delay to allow user to see the success message
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
}, 1500);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: 'background.paper',
|
||||
color: 'text.primary',
|
||||
maxWidth: '500px',
|
||||
width: '100%',
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ fontSize: '1.5rem', fontWeight: 700, pb: 1 }}>
|
||||
Join Our Community
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText sx={{ color: 'text.secondary', mb: 3 }}>
|
||||
Get exclusive access to roadmaps, resources, and updates to accelerate your tech journey.
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>Join Our Mailing List</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Stay updated with the latest news and updates from Do Tech Bro.
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="name"
|
||||
label="Name"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
margin="dense"
|
||||
id="email"
|
||||
label="Email Address"
|
||||
type="email"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<DialogContentText className="mt-2 text-xs text-gray-600">
|
||||
We promise not to sell your information or email you more than once or
|
||||
twice a month.
|
||||
</DialogContentText>
|
||||
{error && (
|
||||
<DialogContentText className="mt-2 text-xs text-red-600">
|
||||
{error}
|
||||
</DialogContentText>
|
||||
|
||||
<TextField
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="name"
|
||||
label="Full Name"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
sx={{
|
||||
mb: 2,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: 'rgba(148, 163, 184, 0.2)',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'primary.main',
|
||||
},
|
||||
},
|
||||
'& .MuiInputLabel-root': {
|
||||
color: 'text.secondary',
|
||||
},
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'text.primary',
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
margin="dense"
|
||||
id="email"
|
||||
label="Email Address"
|
||||
type="email"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
sx={{
|
||||
mb: 2,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: 'rgba(148, 163, 184, 0.2)',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'primary.main',
|
||||
},
|
||||
},
|
||||
'& .MuiInputLabel-root': {
|
||||
color: 'text.secondary',
|
||||
},
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'text.primary',
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<DialogContentText sx={{ mt: 2, fontSize: '0.85rem', color: 'text.secondary', opacity: 0.8 }}>
|
||||
We promise not to sell your information or email you more than once or
|
||||
twice a month.
|
||||
)}
|
||||
{success && (
|
||||
<DialogContentText className="mt-2 text-xs text-green-600">
|
||||
{success}
|
||||
</DialogContentText>
|
||||
|
||||
{error && (
|
||||
<DialogContentText sx={{ mt: 2, color: '#ef4444', fontSize: '0.875rem' }}>
|
||||
{error}
|
||||
</DialogContentText>
|
||||
)}
|
||||
|
||||
{success && (
|
||||
<DialogContentText sx={{ mt: 2, color: 'primary.main', fontSize: '0.875rem' }}>
|
||||
{success}
|
||||
</DialogContentText>
|
||||
)}
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions sx={{ px: 3, pb: 3 }}>
|
||||
<Button
|
||||
onClick={onClose}
|
||||
sx={{
|
||||
color: 'text.secondary',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(148, 163, 184, 0.1)',
|
||||
}
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{
|
||||
px: 4,
|
||||
'&:hover': {
|
||||
backgroundColor: 'primary.dark',
|
||||
}
|
||||
}}
|
||||
>
|
||||
Subscribe
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</ThemeProvider>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSubmit} color="primary">
|
||||
Subscribe
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default MailingListDialog;
|
||||
export default MailingListDialog;
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
const NotFound = () => {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen bg-dark-900 text-white px-4">
|
||||
<div className="text-center max-w-lg">
|
||||
<h1 className="text-8xl font-bold bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent mb-6">404</h1>
|
||||
|
||||
<h2 className="text-3xl font-bold mb-4">Page Not Found</h2>
|
||||
|
||||
<p className="text-gray-300 mb-8">
|
||||
Oops! The page you're looking for doesn't exist or has been moved to a different location.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-4">
|
||||
<Link
|
||||
to="/"
|
||||
className="px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-medium rounded-lg shadow-lg transition-colors"
|
||||
>
|
||||
Return Home
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to="/roadmap"
|
||||
className="px-6 py-3 border-2 border-primary-500 text-primary-400 hover:bg-primary-500/10 font-medium rounded-lg transition-colors"
|
||||
>
|
||||
Explore Roadmaps
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="mt-16">
|
||||
<p className="text-gray-400 mb-2">
|
||||
Think this is a mistake? Let us know!
|
||||
</p>
|
||||
<a
|
||||
href="mailto:support@dotechbro.org"
|
||||
className="text-primary-400 hover:text-primary-300 transition-colors"
|
||||
>
|
||||
support@dotechbro.org
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotFound;
|
|
@ -1,145 +1,12 @@
|
|||
import { Outlet, useLocation, Link } from 'react-router-dom';
|
||||
import challenges from '../challenges';
|
||||
import roadmaps from '../roadmaps.json';
|
||||
import Accordion from './Accordion';
|
||||
|
||||
const Roadmap = () => {
|
||||
const location = useLocation();
|
||||
const isRootPath = location.pathname === '/roadmap';
|
||||
|
||||
return (
|
||||
<div className="bg-dark-900 text-white min-h-screen">
|
||||
{isRootPath ? (
|
||||
<>
|
||||
{/* Hero Section */}
|
||||
<section className="py-16 md:py-24 bg-gradient-to-b from-dark-800 to-dark-900">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-6">Tech Career Roadmaps</h1>
|
||||
<p className="text-xl text-gray-300 leading-relaxed mb-8">
|
||||
Structured pathways to help you navigate your journey into tech, with step-by-step guidance
|
||||
and curated resources tailored for minorities entering the industry.
|
||||
</p>
|
||||
<div className="inline-flex items-center justify-center p-1 rounded-lg bg-gradient-to-r from-primary-500 to-secondary-500">
|
||||
<a href="#roadmaps" className="bg-dark-800 text-white font-medium px-6 py-3 rounded-md hover:bg-dark-700 transition-colors">
|
||||
Explore Roadmaps
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Challenges Section */}
|
||||
<section className="py-16 bg-dark-800" id="challenges">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold mb-8 text-center">Common Challenges</h2>
|
||||
<p className="text-lg text-gray-300 text-center mb-12">
|
||||
We understand the unique obstacles minorities face when entering tech.
|
||||
Here's how our roadmaps address these challenges.
|
||||
</p>
|
||||
<Accordion items={challenges} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Roadmaps Section */}
|
||||
<section className="py-16 bg-gradient-to-b from-dark-900 to-dark-800" id="roadmaps">
|
||||
<div className="container mx-auto px-6">
|
||||
<h2 className="text-3xl font-bold text-center mb-6">Available Roadmaps</h2>
|
||||
<p className="text-lg text-gray-300 text-center max-w-3xl mx-auto mb-12">
|
||||
Select a roadmap that aligns with your interests and goals. Each provides a clear path
|
||||
from beginner to professional.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{roadmaps.map((roadmap, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
to={`/roadmap/${roadmap.id}`}
|
||||
className="group bg-dark-700 rounded-xl overflow-hidden shadow-lg hover:shadow-xl transition-all duration-300 flex flex-col h-full"
|
||||
>
|
||||
<div className="p-1 bg-gradient-to-r from-primary-500 to-secondary-500">
|
||||
<div className="bg-dark-700 p-6 flex-grow">
|
||||
<h3 className="text-2xl font-bold mb-4 group-hover:text-primary-400 transition-colors">
|
||||
{roadmap.title}
|
||||
</h3>
|
||||
<p className="text-gray-300 mb-6">{roadmap.description}</p>
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
{['Beginner-Friendly', 'Step-by-Step', 'Resource Links'].map((tag, i) => (
|
||||
<span key={i} className="text-xs bg-dark-600 text-gray-300 px-2 py-1 rounded-full">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4 bg-dark-600 text-primary-400 font-medium flex justify-between items-center">
|
||||
<span>View Roadmap</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 transform group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||
</svg>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Coming Soon Section */}
|
||||
<section className="py-16 bg-dark-800">
|
||||
<div className="container mx-auto px-6">
|
||||
<div className="bg-gradient-to-r from-dark-700 to-dark-600 rounded-xl p-8 max-w-4xl mx-auto">
|
||||
<h3 className="text-2xl font-bold mb-4 text-center">More Roadmaps Coming Soon</h3>
|
||||
<div className="flex flex-col md:flex-row items-center gap-8">
|
||||
<div className="md:w-3/4">
|
||||
<p className="text-gray-300 mb-4">
|
||||
We're actively developing additional roadmaps for various tech roles including:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-gray-300 mb-4 space-y-2">
|
||||
<li>Cloud Engineering</li>
|
||||
<li>Machine Learning & AI</li>
|
||||
<li>Product Management</li>
|
||||
<li>Cybersecurity</li>
|
||||
<li>Mobile App Development</li>
|
||||
</ul>
|
||||
<p className="text-gray-300">
|
||||
Subscribe to our newsletter to get notified when new roadmaps are released.
|
||||
</p>
|
||||
</div>
|
||||
<div className="md:w-1/4 flex justify-center">
|
||||
<div className="w-24 h-24 rounded-full bg-dark-500 flex items-center justify-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12 text-primary-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contribute Section */}
|
||||
<section className="py-16 bg-gradient-to-b from-dark-800 to-dark-900">
|
||||
<div className="container mx-auto px-6 text-center">
|
||||
<h3 className="text-3xl font-bold mb-6">Open Source Collaboration</h3>
|
||||
<p className="text-lg text-gray-300 mb-8 max-w-2xl mx-auto">
|
||||
These roadmaps are open source and we welcome contributions from the community.
|
||||
Help us improve these resources for everyone.
|
||||
</p>
|
||||
<div className="inline-block bg-gradient-to-r from-primary-500 to-secondary-500 p-0.5 rounded-lg">
|
||||
<button className="px-8 py-3 bg-dark-800 hover:bg-dark-700 text-white font-medium rounded-md transition-colors">
|
||||
Contribute on GitHub
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
) : (
|
||||
<Outlet />
|
||||
)}
|
||||
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">
|
||||
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>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
|
||||
export default Roadmap;
|
||||
export default Roadmap;
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
// src/components/RoadmapDetail.jsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import roadmaps from '../roadmaps.json';
|
||||
|
||||
const RoadmapDetail = () => {
|
||||
const { id } = useParams();
|
||||
const [roadmap, setRoadmap] = useState(null);
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// Find the roadmap with the matching id
|
||||
const foundRoadmap = roadmaps.find(r => r.id === id);
|
||||
if (foundRoadmap) {
|
||||
setRoadmap(foundRoadmap);
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
if (!roadmap) {
|
||||
return (
|
||||
<div className="container mx-auto px-6 py-16 text-center">
|
||||
<h2 className="text-3xl font-bold mb-4">Roadmap Not Found</h2>
|
||||
<p className="text-gray-300 mb-8">We couldn't find the roadmap you're looking for.</p>
|
||||
<Link
|
||||
to="/roadmap"
|
||||
className="px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white rounded-lg transition-colors"
|
||||
>
|
||||
View All Roadmaps
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Mock data for steps (this would come from the roadmap data in a real implementation)
|
||||
const steps = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
description: "Begin your journey by understanding the fundamentals and setting up your learning environment.",
|
||||
content: `
|
||||
<p>Welcome to your tech journey! This first phase is all about building a solid foundation. You'll get familiar with key concepts, tools, and start building habits that will serve you throughout your career.</p>
|
||||
<h4>Key Objectives:</h4>
|
||||
<ul>
|
||||
<li>Understand the field and career opportunities</li>
|
||||
<li>Set up your development environment</li>
|
||||
<li>Learn the fundamental concepts</li>
|
||||
<li>Build your first small projects</li>
|
||||
</ul>
|
||||
`,
|
||||
resources: [
|
||||
{ title: "Free Code Camp", url: "https://www.freecodecamp.org/" },
|
||||
{ title: "The Odin Project", url: "https://www.theodinproject.com/" },
|
||||
{ title: "MDN Web Docs", url: "https://developer.mozilla.org/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Building Skills",
|
||||
description: "Develop core technical skills and start working on meaningful projects.",
|
||||
content: `
|
||||
<p>Now that you have the basics down, it's time to deepen your knowledge and start applying what you've learned to more complex problems and projects.</p>
|
||||
<h4>Key Objectives:</h4>
|
||||
<ul>
|
||||
<li>Master core programming concepts</li>
|
||||
<li>Learn industry-standard tools and frameworks</li>
|
||||
<li>Build a portfolio of projects</li>
|
||||
<li>Practice problem-solving skills</li>
|
||||
</ul>
|
||||
`,
|
||||
resources: [
|
||||
{ title: "LeetCode", url: "https://leetcode.com/" },
|
||||
{ title: "GitHub Learning Lab", url: "https://lab.github.com/" },
|
||||
{ title: "Codecademy", url: "https://www.codecademy.com/" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Professional Development",
|
||||
description: "Prepare for the job market and develop professional skills.",
|
||||
content: `
|
||||
<p>Technical skills are just one part of a successful tech career. In this phase, you'll focus on the professional aspects of working in tech and prepare for your job search.</p>
|
||||
<h4>Key Objectives:</h4>
|
||||
<ul>
|
||||
<li>Create a professional resume and online presence</li>
|
||||
<li>Develop interview skills (technical and behavioral)</li>
|
||||
<li>Build your network and find mentors</li>
|
||||
<li>Learn about industry practices and workflows</li>
|
||||
</ul>
|
||||
`,
|
||||
resources: [
|
||||
{ title: "Tech Interview Handbook", url: "https://www.techinterviewhandbook.org/" },
|
||||
{ title: "LinkedIn Learning", url: "https://www.linkedin.com/learning/" },
|
||||
{ title: "AngelList", url: "https://angel.co/jobs" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Landing Your First Role",
|
||||
description: "Strategies for job searching and excelling in your first position.",
|
||||
content: `
|
||||
<p>This is where all your hard work comes together. You'll apply for jobs, go through interviews, and start your professional journey in tech.</p>
|
||||
<h4>Key Objectives:</h4>
|
||||
<ul>
|
||||
<li>Develop an effective job search strategy</li>
|
||||
<li>Prepare for technical and behavioral interviews</li>
|
||||
<li>Evaluate job offers and negotiate compensation</li>
|
||||
<li>Plan for success in your first 90 days</li>
|
||||
</ul>
|
||||
`,
|
||||
resources: [
|
||||
{ title: "Hired", url: "https://hired.com/" },
|
||||
{ title: "Glassdoor", url: "https://www.glassdoor.com/" },
|
||||
{ title: "Blind", url: "https://www.teamblind.com/" }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-6 py-16">
|
||||
{/* Roadmap Header */}
|
||||
<div className="mb-16 text-center">
|
||||
<Link to="/roadmap" className="text-primary-400 hover:text-primary-300 transition-colors inline-flex items-center mb-6">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clipRule="evenodd" />
|
||||
</svg>
|
||||
Back to Roadmaps
|
||||
</Link>
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-4">{roadmap.title}</h1>
|
||||
<p className="text-xl text-gray-300 max-w-3xl mx-auto">{roadmap.description}</p>
|
||||
</div>
|
||||
|
||||
{/* Progress Indicator */}
|
||||
<div className="mb-12">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t-2 border-dark-600"></div>
|
||||
</div>
|
||||
<div className="relative flex justify-between">
|
||||
{steps.map((step, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setActiveStep(index)}
|
||||
className={`flex items-center justify-center w-12 h-12 rounded-full text-lg font-bold ${
|
||||
index === activeStep
|
||||
? 'bg-primary-500 text-white shadow-lg'
|
||||
: index < activeStep
|
||||
? 'bg-primary-800 text-primary-200'
|
||||
: 'bg-dark-600 text-gray-400'
|
||||
} transition-all duration-300`}
|
||||
>
|
||||
{index + 1}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex justify-between">
|
||||
{steps.map((step, index) => (
|
||||
<div key={index} className={`text-center w-1/4 px-2 ${
|
||||
index === activeStep ? 'text-white' : 'text-gray-400'
|
||||
}`}>
|
||||
<h4 className="font-medium text-sm md:text-base truncate">{step.title}</h4>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Active Step Content */}
|
||||
<div className="bg-dark-800 rounded-xl shadow-lg overflow-hidden">
|
||||
<div className="p-1 bg-gradient-to-r from-primary-500 to-secondary-500">
|
||||
<div className="bg-dark-800 p-8">
|
||||
<h2 className="text-3xl font-bold mb-2">{steps[activeStep].title}</h2>
|
||||
<p className="text-xl text-gray-300 mb-6">{steps[activeStep].description}</p>
|
||||
|
||||
<div className="prose prose-invert max-w-none mb-8" dangerouslySetInnerHTML={{ __html: steps[activeStep].content }}></div>
|
||||
|
||||
<div className="bg-dark-700 p-6 rounded-lg">
|
||||
<h3 className="text-xl font-bold mb-4">Recommended Resources</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{steps[activeStep].resources.map((resource, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={resource.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-dark-600 hover:bg-dark-500 p-4 rounded-lg transition-colors flex items-center"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2 text-primary-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
<span>{resource.title}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Buttons */}
|
||||
<div className="mt-8 flex justify-between">
|
||||
<button
|
||||
onClick={() => setActiveStep(Math.max(0, activeStep - 1))}
|
||||
disabled={activeStep === 0}
|
||||
className={`flex items-center px-6 py-3 rounded-lg transition-colors ${
|
||||
activeStep === 0
|
||||
? 'bg-dark-700 text-gray-500 cursor-not-allowed'
|
||||
: 'bg-dark-700 hover:bg-dark-600 text-white'
|
||||
}`}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
Previous Step
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setActiveStep(Math.min(steps.length - 1, activeStep + 1))}
|
||||
disabled={activeStep === steps.length - 1}
|
||||
className={`flex items-center px-6 py-3 rounded-lg transition-colors ${
|
||||
activeStep === steps.length - 1
|
||||
? 'bg-dark-700 text-gray-500 cursor-not-allowed'
|
||||
: 'bg-primary-600 hover:bg-primary-700 text-white'
|
||||
}`}
|
||||
>
|
||||
Next Step
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Community Support Section */}
|
||||
<div className="mt-16 bg-dark-700 rounded-xl p-8 text-center">
|
||||
<h3 className="text-2xl font-bold mb-4">Need Support?</h3>
|
||||
<p className="text-gray-300 mb-6">
|
||||
Join our community to connect with mentors and peers who are on similar journeys.
|
||||
Get answers to your questions and share your progress.
|
||||
</p>
|
||||
<button className="px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white rounded-lg transition-colors">
|
||||
Join Our Community
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoadmapDetail;
|
153
src/index.css
153
src/index.css
|
@ -4,184 +4,65 @@
|
|||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
background-color: #0f172a;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Base typography scale */
|
||||
--font-size-xs: 0.75rem;
|
||||
--font-size-sm: 0.875rem;
|
||||
--font-size-base: 1rem;
|
||||
--font-size-lg: 1.125rem;
|
||||
--font-size-xl: 1.25rem;
|
||||
--font-size-2xl: 1.5rem;
|
||||
--font-size-3xl: 1.875rem;
|
||||
--font-size-4xl: 2.25rem;
|
||||
--font-size-5xl: 3rem;
|
||||
|
||||
/* Spacing scale */
|
||||
--spacing-0: 0;
|
||||
--spacing-1: 0.25rem;
|
||||
--spacing-2: 0.5rem;
|
||||
--spacing-3: 0.75rem;
|
||||
--spacing-4: 1rem;
|
||||
--spacing-6: 1.5rem;
|
||||
--spacing-8: 2rem;
|
||||
--spacing-12: 3rem;
|
||||
--spacing-16: 4rem;
|
||||
|
||||
/* Colors */
|
||||
--color-primary: #22c55e;
|
||||
--color-primary-dark: #15803d;
|
||||
--color-primary-light: #4ade80;
|
||||
--color-secondary: #6366f1;
|
||||
--color-secondary-dark: #4338ca;
|
||||
--color-secondary-light: #818cf8;
|
||||
--color-dark: #0f172a;
|
||||
--color-dark-lighter: #1e293b;
|
||||
--color-gray: #64748b;
|
||||
--color-gray-light: #94a3b8;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: var(--color-secondary);
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--color-secondary-light);
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
background-color: var(--color-dark);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--font-size-4xl);
|
||||
margin-bottom: var(--spacing-6);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--font-size-3xl);
|
||||
margin-bottom: var(--spacing-4);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: var(--font-size-2xl);
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--spacing-4);
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0.5rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: var(--color-dark-lighter);
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: var(--color-primary);
|
||||
background-color: rgba(34, 197, 94, 0.1);
|
||||
border-color: #646cff;
|
||||
}
|
||||
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Custom utility classes */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.5rem 1.5rem;
|
||||
font-weight: 500;
|
||||
border-radius: 0.5rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--color-secondary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--color-secondary-dark);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--color-primary);
|
||||
color: #fff;
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #334155;
|
||||
background-color: #f8fafc;
|
||||
|
||||
--color-dark: #f8fafc;
|
||||
--color-dark-lighter: #f1f5f9;
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f8fafc;
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #e2e8f0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: rgba(34, 197, 94, 0.1);
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,116 +6,9 @@ export default {
|
|||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: {
|
||||
50: '#f0fdf4',
|
||||
100: '#dcfce7',
|
||||
200: '#bbf7d0',
|
||||
300: '#86efac',
|
||||
400: '#4ade80',
|
||||
500: '#22c55e',
|
||||
600: '#16a34a',
|
||||
700: '#15803d',
|
||||
800: '#166534',
|
||||
900: '#14532d',
|
||||
950: '#052e16',
|
||||
},
|
||||
secondary: {
|
||||
50: '#eef2ff',
|
||||
100: '#e0e7ff',
|
||||
200: '#c7d2fe',
|
||||
300: '#a5b4fc',
|
||||
400: '#818cf8',
|
||||
500: '#6366f1',
|
||||
600: '#4f46e5',
|
||||
700: '#4338ca',
|
||||
800: '#3730a3',
|
||||
900: '#312e81',
|
||||
950: '#1e1b4b',
|
||||
},
|
||||
dark: {
|
||||
50: '#f9fafb',
|
||||
100: '#f3f4f6',
|
||||
200: '#e5e7eb',
|
||||
300: '#d1d5db',
|
||||
400: '#9ca3af',
|
||||
500: '#6b7280',
|
||||
600: '#4b5563',
|
||||
700: '#374151',
|
||||
800: '#1f2937',
|
||||
900: '#111827',
|
||||
950: '#030712',
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'system-ui', 'sans-serif'],
|
||||
inter: ['Inter', 'sans-serif'],
|
||||
},
|
||||
fontSize: {
|
||||
xs: ['0.75rem', { lineHeight: '1rem' }],
|
||||
sm: ['0.875rem', { lineHeight: '1.25rem' }],
|
||||
base: ['1rem', { lineHeight: '1.5rem' }],
|
||||
lg: ['1.125rem', { lineHeight: '1.75rem' }],
|
||||
xl: ['1.25rem', { lineHeight: '1.75rem' }],
|
||||
'2xl': ['1.5rem', { lineHeight: '2rem' }],
|
||||
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
|
||||
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
|
||||
'5xl': ['3rem', { lineHeight: '1.16' }],
|
||||
'6xl': ['3.75rem', { lineHeight: '1.16' }],
|
||||
},
|
||||
spacing: {
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'20': '5rem',
|
||||
'24': '6rem',
|
||||
'32': '8rem',
|
||||
'40': '10rem',
|
||||
'48': '12rem',
|
||||
'56': '14rem',
|
||||
'64': '16rem',
|
||||
'72': '18rem',
|
||||
'80': '20rem',
|
||||
'96': '24rem',
|
||||
},
|
||||
borderRadius: {
|
||||
'none': '0',
|
||||
'sm': '0.125rem',
|
||||
DEFAULT: '0.25rem',
|
||||
'md': '0.375rem',
|
||||
'lg': '0.5rem',
|
||||
'xl': '0.75rem',
|
||||
'2xl': '1rem',
|
||||
'3xl': '1.5rem',
|
||||
'full': '9999px',
|
||||
},
|
||||
boxShadow: {
|
||||
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
||||
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
||||
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
||||
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
||||
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
||||
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
||||
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
|
||||
none: 'none',
|
||||
},
|
||||
animation: {
|
||||
'dropdown': 'dropdown 0.3s ease-in-out',
|
||||
},
|
||||
keyframes: {
|
||||
dropdown: {
|
||||
'0%': { opacity: 0, transform: 'translateY(-10px)' },
|
||||
'100%': { opacity: 1, transform: 'translateY(0)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
|
|
Loading…
Add table
Reference in a new issue