Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions LocalMind-Frontend/src/app/pages/Contributors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import React, { useMemo, useState } from "react";
import { CONTRIBUTORS, type Contributor } from "../../data/contributors";
import s from "./contributors.module.css";

const REPO_ISSUE_NEW_URL = "https://github.com/NexGenStudioDev/LocalMind/issues/new";

function enc(x: string) {
return encodeURIComponent(x);
}

function buildNewIssueUrl(c: Contributor) {
const title = `Add contributor: ${c.name}`;

const body = `Hi maintainers,
Please add me to the Contributors page.

Name: ${c.name}
Email: ${c.email}
GitHub: ${c.github}
LinkedIn: ${c.linkedin}
Bio: ${c.bio}
Area of contribution (optional): ${c.area ?? ""}
Tags (optional): ${(c.tags ?? []).join(", ")}

Notes:
- Beginners are welcome.
- No contribution is too small.
`;

return `${REPO_ISSUE_NEW_URL}?title=${enc(title)}&body=${enc(body)}`;
}

export default function ContributorsPage() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [github, setGithub] = useState("");
const [linkedin, setLinkedin] = useState("");
const [bio, setBio] = useState("");
const [area, setArea] = useState("");
const [tags, setTags] = useState("");

const list = CONTRIBUTORS;

const issueUrl = useMemo(() => {
const c: Contributor = {
name: name.trim(),
email: email.trim(),
github: github.trim(),
linkedin: linkedin.trim(),
bio: bio.trim(),
area: area.trim() || undefined,
tags: tags
.split(",")
.map((t) => t.trim())
.filter(Boolean),
};

return c.name && c.email && c.github && c.linkedin && c.bio
? buildNewIssueUrl(c)
: "";
}, [name, email, github, linkedin, bio, area, tags]);

return (
<div className={s.cwrap}>
<header className={s.chead}>
<h1>Contributors</h1>
<p className={s.csub}>
This project grows because people like you show up and help. Beginners
are welcome, and no contribution is too small.
</p>
</header>

<section className={s.csec}>
<h2>People who contributed</h2>

<div className={s.cgrid}>
{list.map((c) => (
<article key={c.github + c.email} className={s.ccard}>
<div className={s.ctop}>
<h3 className={s.cname}>{c.name}</h3>
{c.area ? <span className={s.cpill}>{c.area}</span> : null}
</div>

<p className={s.cbio}>{c.bio}</p>

<div className={s.clinks}>
<a href={`mailto:${c.email}`} target="_blank" rel="noreferrer">
{c.email}
</a>
<a href={c.github} target="_blank" rel="noopener noreferrer">
GitHub
</a>
<a href={c.linkedin} target="_blank" rel="noopener noreferrer">
LinkedIn
</a>
</div>

{c.tags && c.tags.length ? (
<div className={s.ctags}>
{c.tags.map((t) => (
<span key={t} className={s.ctag}>
{t}
</span>
))}
</div>
) : null}
</article>
))}
</div>
</section>

<section className={s.csec}>
<h2>How to become a contributor</h2>
<ul className={s.clist}>
<li>Pick an issue labeled “good first issue” (or any small task).</li>
<li>Fork the repo, create a new branch, and make a focused change.</li>
<li>Open a pull request and describe what you changed and why.</li>
<li>Ask questions—collaboration helps everyone grow.</li>
</ul>
</section>

<section className={s.csec}>
<h2>Add your details</h2>

<p className={s.csub}>
Fill the fields below and click “Create request”. It will open a
GitHub issue with your details prefilled.
</p>

<div className={s.cform}>
<label>
Name *
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Your full name"
/>
</label>

<label>
Email *
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
/>
</label>

<label>
GitHub profile link *
<input
value={github}
onChange={(e) => setGithub(e.target.value)}
placeholder="https://github.com/username"
/>
</label>

<label>
LinkedIn profile link *
<input
value={linkedin}
onChange={(e) => setLinkedin(e.target.value)}
placeholder="https://www.linkedin.com/in/username/"
/>
</label>

<label>
Short bio *
<textarea
value={bio}
onChange={(e) => setBio(e.target.value)}
placeholder="2–3 lines about you"
/>
</label>

<label>
Area of contribution (optional)
<input
value={area}
onChange={(e) => setArea(e.target.value)}
placeholder="Docs / Frontend / Backend / Design..."
/>
</label>

<label>
Tags (optional, comma-separated)
<input
value={tags}
onChange={(e) => setTags(e.target.value)}
placeholder="react, typescript, ui"
/>
</label>

<div className={s.cactions}>
<button
className={s.cbtn}
disabled={!issueUrl}
onClick={() => window.open(issueUrl, "_blank", "noopener,noreferrer")}
type="button"
title={!issueUrl ? "Fill all required fields first" : "Open GitHub issue"}
>
Create request (opens GitHub)
</button>

<a
className={s.clink}
href={REPO_ISSUE_NEW_URL}
target="_blank"
rel="noreferrer"
>
Or open a blank issue
</a>
</div>
</div>
</section>
</div>
);
}
46 changes: 46 additions & 0 deletions LocalMind-Frontend/src/app/pages/contributors.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.cwrap { max-width: 1050px; margin: 0 auto; padding: 24px 16px 60px; }
.chead h1 { margin: 0 0 8px; font-size: 34px; }
.csub { margin: 0; opacity: 0.85; line-height: 1.5; }
.csec { margin-top: 28px; }
.csec h2 { margin: 0 0 12px; font-size: 20px; }

.cgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
.ccard { border: 1px solid rgba(0,0,0,0.12); border-radius: 12px; padding: 14px; background: #fff; }
.ctop { display: flex; gap: 10px; align-items: center; justify-content: space-between; }
.cname { margin: 0; font-size: 16px; }
.cpill { font-size: 12px; padding: 4px 8px; border-radius: 999px; background: rgba(0,0,0,0.06); }
.cbio { margin: 10px 0; line-height: 1.45; opacity: 0.9; }

.clinks { display: flex; gap: 12px; flex-wrap: wrap; }
.clinks a { text-decoration: none; color: #2563eb; }
.clinks a:hover { text-decoration: underline; }

.ctags { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 8px; }
.ctag { font-size: 12px; padding: 4px 8px; border-radius: 999px; border: 1px solid rgba(0,0,0,0.12); }

.clist { margin: 10px 0 0; padding-left: 18px; line-height: 1.6; }

.cform { display: grid; gap: 10px; max-width: 650px; }
.cform label { display: grid; gap: 6px; font-size: 13px; opacity: 0.95; }
.cform input, .cform textarea {
width: 100%;
border: 1px solid rgba(0,0,0,0.16);
border-radius: 10px;
padding: 10px 12px;
font-size: 14px;
outline: none;
}
.cform textarea { min-height: 90px; resize: vertical; }

.cactions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 6px; }
.cbtn {
border: none;
border-radius: 10px;
padding: 10px 14px;
background: #111827;
color: white;
cursor: pointer;
}
.cbtn:disabled { opacity: 0.5; cursor: not-allowed; }
.clink { color: #2563eb; text-decoration: none; }
.clink:hover { text-decoration: underline; }
4 changes: 4 additions & 0 deletions LocalMind-Frontend/src/app/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { Route, Routes } from 'react-router-dom'
import HomePage from '../../features/Dashboard/V1/Component/Pages/HomePage'
import LoginPage from '../../shared/component/v1/LoginPage'
import ContributorsPage from "../pages/Contributors";

const AppRoutes: React.FC = () => {
return (
Expand All @@ -19,6 +20,9 @@ const AppRoutes: React.FC = () => {
<Route path="/forgot-password" element={<LoginPage />} />

{/* Chat Page */}

{/* Contributors page*/}
<Route path="/contributors" element={<ContributorsPage />} />
</Routes>
)
}
Expand Down
21 changes: 21 additions & 0 deletions LocalMind-Frontend/src/data/contributors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export type Contributor = {
name: string;
email: string;
github: string;
linkedin: string;
bio: string;
area?: string; // optional
tags?: string[]; // optional
};

export const CONTRIBUTORS: Contributor[] = [
{
name: "Abhishek Kumar",
email: "example@email.com",
github: "https://github.com/abhishek-nexgen-dev",
linkedin: "https://www.linkedin.com/in/your-link/",
bio: "Aspiring software engineer. Interested in building friendly open-source tools.",
area: "Core development",
tags: ["frontend", "typescript"],
},
];
5 changes: 5 additions & 0 deletions LocalMind-Frontend/src/shared/component/v1/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import Artificialintelligence from '../../../assets/Artificial intelligence.png'
import { NavLink } from 'react-router-dom'


const Navbar: React.FC = () => {
const navLinkClass = ({ isActive }: { isActive: boolean }) =>
isActive ? 'text-white line-through opacity-80' : 'text-white'
Expand All @@ -26,6 +27,10 @@ const Navbar: React.FC = () => {
<NavLink to="/play-ground" className={navLinkClass}>
PlayGround
</NavLink>
<NavLink to="/contributors" className={navLinkClass}>
Contributors
</NavLink>

</div>

<NavLink
Expand Down