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
39 changes: 38 additions & 1 deletion Frontend-team/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Frontend-team/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@hookform/resolvers": "^3.9.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.1",
"@reduxjs/toolkit": "^2.3.0",
Expand All @@ -23,13 +24,15 @@
"octokit": "^4.0.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.54.2",
"react-redux": "^9.1.2",
"react-router-dom": "^6.28.0",
"react-tag-autocomplete": "^7.4.0",
"react-tag-maker": "^1.1.0",
"tailwind-merge": "^2.5.4",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"zod": "^3.24.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
Expand Down
2 changes: 1 addition & 1 deletion Frontend-team/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ function App() {
);
}

export default App;
export default App;
6 changes: 3 additions & 3 deletions Frontend-team/src/components/Github.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ const GitHubAuth: React.FC = () => {
}
}, []);

const handleLogin = () => {
window.location.href = "https://ethopensource.onrender.com/auth/github";
};
// const handleLogin = () => {
// window.location.href = "https://ethopensource.onrender.com/auth/github";
// };

return (
<div style={{ textAlign: "center", marginTop: "500px" }} className="">
Expand Down
43 changes: 21 additions & 22 deletions Frontend-team/src/components/Layout/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@ import { Navbar } from 'flowbite-react';
import { useState } from 'react';
import CustomBtn from '../Common/CustomBtn';
import { Link, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { useSelector } from 'react-redux';
import { RootState } from '@/store';
// import { DarkThemeToggle } from 'flowbite-react';
import notificationIcon from "../../assets/icons/notificationIcon.svg"
import {
// loginWithGitHub,
// loginWithGoogle,
// loginWithEmailPassword, loginWithGitHub, loginWithGoogle,
logout } from '@/store/actions/auth';
import git from "../../assets/icons/gith.svg";
import githubIcon from "../../assets/icons/githubIcon.png";

// import git from "../../assets/icons/gith.svg";
// import { Button } from '../ui/button';
import { setLoginType } from '@/store/actions/onboardState';
// import { setLoginType } from '@/store/actions/onboardState';
import { redirectToGitHubAuth } from '@/services/api';
export default function Navigation() {
const [activeLink, setActiveLink] = useState('Home'); // Initial active link
const { user } = useSelector((state: RootState) => state.auth);
// const { loginType:isLogin } = useSelector((state: RootState) => state.onboardState);
const [isProfile, setIsProfile] = useState(false);
// const [isDroped, setIsDroped] = useState(false);
const dispatch = useDispatch();
// const dispatch = useAppDispatch();

// const { role, loginType } = useSelector((state: RootState) => state.onboardState);


Expand All @@ -30,16 +29,16 @@ export default function Navigation() {
// // { title: "Login with Google", icon: google, type:"google" },
// ]

const handleLogin = (logintype:string,) => {
dispatch(setLoginType(logintype))
if(logintype === "github"){
navigate("/onboarding")
// const handleLogin = (logintype:string,) => {
// dispatch(setLoginType(logintype))
// if(logintype === "github"){
// navigate("/onboarding")

} else if(logintype === "google"){
// dispatch(loginWithGoogle())
navigate("/onboarding")
}
}
// } else if(logintype === "google"){
// // dispatch(loginWithGoogle())
// navigate("/onboarding")
// }
// }
// const DropdownLogin = () => {
// return (<div className='bg-white text-black p-7 rounded-xl flex flex-col gap-3'>
// <h3 className="text-base font-medium border-b border-opacity-20 p-2">Choose Login Type</h3>
Expand All @@ -59,7 +58,7 @@ export default function Navigation() {

// </div>)
// }

// console.log(user)
return (
<Navbar className="fixed w-full z-50 bg-opacity-90 dark:bg-opacity-5 backdrop-blur-sm py-6 px-5 m-0">
<Navbar.Brand href="/">
Expand All @@ -69,16 +68,16 @@ export default function Navigation() {

{user ? <div className="flex gap-5">
<CustomBtn text={``} colored="yes" icon={notificationIcon} btnstyle="p-0" iconStyle="w-3 h-3 rounded-full" style="flex w-[48px] h-[48px] max-sm:w-[32px] max-sm:h-[32px]" onClick={() => { navigate("/notifications") }} />
<CustomBtn text={`${user?.username?.slice(0, 9)}...`} icon={user.photoURL} iconStyle="w-8 h-8 rounded-full" colored="yes" style="hidden md:flex w-[137px] text-[16px]" onClick={() => setIsProfile(!isProfile)} />
<CustomBtn text={`${user?.email?.slice(0, 9)}...`} icon={user.photoURL} iconStyle="w-8 h-8 rounded-full" colored="yes" style="hidden md:flex w-[137px] text-[16px]" onClick={() => setIsProfile(!isProfile)} />
<CustomBtn text={``} icon={user.photoURL} btnstyle="p-0" iconStyle="w-8 h-8 rounded-full" colored="yes" style="md:hidden flex max-sm:w-fit max-sm:h-fit text-[16px]" onClick={() => setIsProfile(!isProfile)} />
{isProfile && <div className="absolute top-12 right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabIndex={-1}>
<Link to="/profile" onClick={() => setIsProfile(false)} className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-0">Your Profile</Link>
<a href="#" onClick={() => setIsProfile(false)} className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-1">Settings</a>
<a href="#" className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-2" onClick={() => { dispatch(logout() as any); setIsProfile(false) }}>Sign out</a>
<a href="#" className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-2" onClick={() => { setIsProfile(false) }}>Sign out</a>
</div>}
</div> :
<div className="relative">
<CustomBtn icon={git} text={`Connect with GitHub`} colored="yes" style="hidden md:flex" onClick={() => handleLogin("github")} />
<CustomBtn icon={githubIcon} text={`Connect with GitHub`} colored="yes" style="hidden md:flex" onClick={() => redirectToGitHubAuth()} />
</div>
}
{/* <DarkThemeToggle /> */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const ExploreProjec = () => {
return (
<div className="relative flex mt-16 max-sm:mr-4 ">
<div className="relative flex w-full ">
<div className="absolute gap-2 inset-y-0 start-0 flex items-center pointer-events-none ps-3 ">
<svg
className="w-4 h-4 text-gray-500 dark:text-gray-400 ml-3"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { useState } from "react";

interface ModalProps {
isOpen: boolean;
onClose: () => void;
onSubmit: (formData: FormData) => void;
}

const CreateProjectModal: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const [formValues, setFormValues] = useState({
title: "",
description: "",
type: "",
rewards: "",
experienceLevel: "",
skillsRequired: "",
projectImage: null as File | null,
});

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
// onSubmit("")
};

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setFormValues({ ...formValues, projectImage: e.target.files[0] });
}
};

// console.log(formValues)

const handleSubmit = () => {
const formData = new FormData();
// Object.entries(formValues).forEach(([key, value]) => {
// if (value) formData.append(key, value as any);
// });
// onSubmit(formValues as any);
console.log(formData)
};

if (!isOpen) return null;

return (
<div className="absolute inset-0 bg-gray-800 bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white p-6 rounded-lg shadow-lg w-96">
<h2 className="text-lg font-semibold mb-4">Create New Project</h2>
<div className="space-y-4 text-black">
<input
type="text"
name="title"
placeholder="Title"
value={formValues.title}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<textarea
name="description"
placeholder="Description"
value={formValues.description}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<input
type="text"
name="type"
placeholder="Type"
value={formValues.type}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<input
type="text"
name="rewards"
placeholder="Rewards"
value={formValues.rewards}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<input
type="text"
name="experienceLevel"
placeholder="Experience Level"
value={formValues.experienceLevel}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<input
type="text"
name="skillsRequired"
placeholder="Skills Required"
value={formValues.skillsRequired}
onChange={handleInputChange}
className="w-full p-2 border rounded"
/>
<input
type="file"
name="projectImage"
onChange={handleFileChange}
className="w-full"
/>
</div>
<div className="mt-4 flex justify-end space-x-2">
<button
onClick={onClose}
className="px-4 py-2 bg-gray-300 rounded hover:bg-gray-400"
>
Cancel
</button>
<button
onClick={handleSubmit}
className="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600"
>
Submit
</button>
</div>
</div>
</div>
);
};

export default CreateProjectModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Upload } from 'lucide-react';

interface FileUploadProps {
onUpload: (e: React.ChangeEvent<HTMLInputElement>) => void;
accept?: string;
maxSize?: string;
visual?: File | null;
}

export function FileUpload({ onUpload, accept = "image/*", maxSize = "800×400px", visual}: FileUploadProps) {
return (
<div className="border-2 border-dashed border-gray-200 rounded-lg p-8">
<input
type="file"
accept={accept}
onChange={onUpload}
className="hidden"
id="visual-upload"
/>
{visual ? <img src={URL.createObjectURL(visual)} alt="Uploaded Visual" className='' /> : <label htmlFor="visual-upload" className="cursor-pointer">
<div className="flex flex-col items-center text-center">
<Upload className="w-6 h-6 text-gray-400 mb-2" />
<p className="text-sm">
<span className="text-purple-600">Click to upload</span> or drag and drop
</p>
<p className="text-xs text-gray-500">SVG, PNG, JPG or GIF (max. {maxSize})</p>
</div>
</label>}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';

interface FormFieldProps {
label: string;
error?: string;
children: React.ReactNode;
}

export function FormField({ label, error, children }: FormFieldProps) {
return (
<div>
<label className="block text-sm text-gray-500 mb-2">{label}</label>
{children}
{error && <p className="text-red-500 text-sm mt-1">{error}</p>}
</div>
);
}
Loading