Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Org dash #248

Open
wants to merge 36 commits into
base: truth-redefined-again
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
705d57c
feat: init dashboard structure
Bikram-ghuku Oct 29, 2024
2fcb75e
feat: reject, accept logic, project type
Bikram-ghuku Oct 29, 2024
2381254
feat: add constants and types
Bikram-ghuku Oct 29, 2024
7638188
feat: spelling mistake
Bikram-ghuku Oct 29, 2024
729ffe8
feat: add pagination based selection
Bikram-ghuku Oct 29, 2024
6e66c30
feat: add basic styles
Bikram-ghuku Oct 29, 2024
ebee55a
feat: update basic ui
Bikram-ghuku Oct 29, 2024
0ad4206
feat: pass the onClick parameter
Bikram-ghuku Oct 29, 2024
15f9b93
feat: updated basic ui
Bikram-ghuku Oct 29, 2024
71451ef
fix: table no update on different btn click
Bikram-ghuku Oct 29, 2024
38fdd4d
feat: add condiitonal button
Bikram-ghuku Oct 29, 2024
35bc276
feat: update styles
Bikram-ghuku Oct 29, 2024
af166c0
feat: lots of changes
Bikram-ghuku Oct 29, 2024
3cb56ba
Merge branch 'kwoc24' into org-dash
Bikram-ghuku Oct 29, 2024
3c7faea
feat: merge
Bikram-ghuku Oct 29, 2024
d4dcd8b
feat: update paths
Bikram-ghuku Oct 29, 2024
947a4d8
feat: added modal
Bikram-ghuku Oct 29, 2024
bdb9ee7
fix: load first element per option
Bikram-ghuku Oct 29, 2024
8d8b95f
Merge branch 'kwoc24' into org-dash
Bikram-ghuku Nov 1, 2024
993cfa8
fix: merge conflicts
Bikram-ghuku Nov 16, 2024
27c2aaf
feat: add dashboard routes
Bikram-ghuku Nov 16, 2024
bb23670
feat: merge latest branch
Bikram-ghuku Nov 20, 2024
f8e9d9b
feat: add backend request, organiser type
Bikram-ghuku Nov 20, 2024
bc4ae07
feat: update response params
Bikram-ghuku Nov 26, 2024
5f9377c
feat: include read org permission
Bikram-ghuku Nov 26, 2024
34d0235
feat: update styles
Bikram-ghuku Nov 26, 2024
f2d6582
Merge branch 'truth-redefined-again' into org-dash
Bikram-ghuku Nov 26, 2024
2dc4c93
feat: updated organiser dashboard
Bikram-ghuku Nov 26, 2024
e57dee7
feat: updated organiser dashboard
Bikram-ghuku Nov 26, 2024
8d3d41d
feat: show status on reject
Bikram-ghuku Nov 26, 2024
0e85443
fix: preset status msg
Bikram-ghuku Nov 26, 2024
f6860bf
fix: pagination length
Bikram-ghuku Nov 27, 2024
67fbe1f
feat: update login workflow, ui changes
Bikram-ghuku Nov 27, 2024
63191d8
feat: make ui heights fixed
Bikram-ghuku Nov 28, 2024
c25952d
feat: updated endpoint
Bikram-ghuku Nov 29, 2024
6110123
feat: updated working for organisers to be mentors
Bikram-ghuku Nov 29, 2024
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
2,334 changes: 1,264 additions & 1,070 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import StudentDashboard from "./pages/StudentDashboard";
import RegistrationForm from "./pages/RegistrationForm";
import { Header } from "./components/Header";
import Footer from "./components/Footer";
import OrgDash from "./pages/OrgDash";

function App() {
return (
Expand Down Expand Up @@ -54,6 +55,10 @@ function App() {
path={ROUTER_PATHS.MENTOR_DASHBOARD}
element={<MentorDashboard />}
/>
<Route
path={ROUTER_PATHS.ORGANISOR_DASHBOARD}
element={<OrgDash/>}
/>
<Route
path={ROUTER_PATHS.PASTPROGRAMS}
element={<PastProgramsPage />}
Expand Down
81 changes: 81 additions & 0 deletions src/components/ListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useState } from "react"
import { Project } from "../util/types"
import OrgDashModal from "./OrgDashModal"

function ListItem({ item } : {item : Project}) {
const [isOpen, setIsOpen] = useState<boolean>(false);
const [isReject, setIsReject] = useState<boolean>(false);
const [actProj, setACtProject] = useState<Project>({} as Project);

const closeModal = () => setIsOpen(false);
const openModal = (isReject: boolean) => {
setIsOpen(true);
setIsReject(isReject);
setACtProject(item);
}
return (
<div className="ls-comp">
<h3 className="ls-comp-name">{item.name}</h3>
<div className="ls-comp-tags">
{
item.tags.map((ele) => (
<div className="ls-comp-tag">
{ele}
</div>
))
}
</div>
<p className="ls-comp-desc">{item.description}</p>
<div className="ls-comp-prs">Total Pulls: {item.pull_count}</div>
<div className="ls-comp-mentor">
Mentor:
<a href={'https://github.com/' + item.mentor.username}>
{'@'+item.mentor.username}
</a>
</div>
<div className="ls-comp-mentor-b">
Secondary Mentor:
<a href={'https://github.com/' + item.secondary_mentor.username}>
{'@'+item.secondary_mentor.name}
</a>
</div>
<div className="ls-comp-pull">{item.pull_count}</div>
<div className="ls-comp-info-btn">
<a className="ls-btn-repo ls-btn" href={item.repo_link}>View Project</a>
<a className="ls-btn-readme ls-btn" href={item.readme_link}>ReadMe</a>
<a className="ls-btn-comm ls-btn" href={item.comm_channel}>Join Channel</a>
</div>
<div className="ls-status-mark">
{item.status_remark && (
item.project_status ?
<div className="ls-status-accept">Accepted</div> :
<div className="ls-status-reject">Rejected</div>
)}
</div>
<div className="ls-compo-action-btn">
{!item.status_remark ? (
<>
<button className="approve-btn" onClick={() => openModal(false)}>Accept</button>
<button className="reject-btn" onClick={() => openModal(true)}>Reject</button>
</>
) : (
item.project_status ? (
<>
<button className="review-btn" onClick={() => openModal(false)}>Review</button>
<button className="reject-btn" onClick={() => openModal(true)}>Reject</button>
</>
) : (
<>
<button className="approve-btn" onClick={() => openModal(false)}>Accept</button>
<button className="review-btn" onClick={() => openModal(true)}>Review</button>
</>
)
)}

</div>
{isOpen && <OrgDashModal isReject={isReject} onClose={closeModal} project={actProj}/>}
</div>
)
}

export default ListItem
58 changes: 58 additions & 0 deletions src/components/OrgDashModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useState } from "react";
import "../styles/OrgDashModal.css"
import { BACKEND_URL } from "../util/constants";
import { useAuthContext } from "../util/auth";
import { Project } from "../util/types";

function OrgDashModal({ isReject, onClose, project } : {isReject : boolean, onClose : () => void, project: Project}) {
const authContext = useAuthContext();
const handleWrapperClick = (e: React.MouseEvent<HTMLDivElement>) => {
if (e.target === e.currentTarget) {
onClose();
}
};

const [review, setReview] = useState<string>(project.status_remark!);

const onBtnClick = () => {
fetch(`${BACKEND_URL}/project/`, {
method: "PUT",
headers: {
'Bearer' : `${authContext.jwt} `
},
body: JSON.stringify({
...project,
"project_status": !isReject,
"status_remark": review,
})
}).then((resp) => {
if(resp.ok){
project.project_status = !isReject;
project.status_remark = review;
onClose();
}
})
}
return (
<div className="modal-main" onClick={handleWrapperClick}>
<div className="modal-wrapper">
<div className="modal-content">
<div className="modal-title">
Why do you want to {isReject ? "reject" : "approve"} the project?
</div>
<div className="modal-inp">
<textarea className="modal-textarea" placeholder="Enter your review..." onChange={(e) => setReview(e.target.value)}>
{project.status_remark}
</textarea>
</div>
<div className="modal-btn">
<button className="modal-cancel" onClick={onClose}>Cancel</button>
{isReject ? <button className="reject-btn" onClick={onBtnClick}>Reject</button> : <button className="approve-btn" onClick={onBtnClick}>Approve</button>}
</div>
</div>
</div>
</div>
)
}

export default OrgDashModal
Empty file removed src/constants.ts
Empty file.
2 changes: 1 addition & 1 deletion src/pages/MentorDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function MentorDashboard() {
navigate(ROUTER_PATHS.STUDENT_DASHBOARD);
}

if (authContext.userData.type !== "mentor") {
if (authContext.userData.type !== "mentor" && authContext.userData.type !== "organiser") {
navigate(ROUTER_PATHS.HOME);
}
}, [authContext]);
Expand Down
118 changes: 118 additions & 0 deletions src/pages/OrgDash.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { useEffect, useState } from 'react'
import ListItem from '../components/ListItem'
import { Project } from '../util/types'
import { BACKEND_URL, GH_OAUTH_ORG_URL, PAGENATION_LEN, ROUTER_PATHS } from '../util/constants'
import '../styles/OrgDash.css'
import { useAuthContext } from '../util/auth'
import { useNavigate } from 'react-router-dom'

function OrgDash() {
const navigate = useNavigate();
const authContext = useAuthContext();
const [allData, setAllData] = useState<Project[]>([]);
const [filterData, setFilterData] = useState<Project[]>([]);
const [currPage, setCurrPage] = useState<Project[]>([]);
const [pgNo, setPgNo] = useState<number>(0);

useEffect(() => {
if (!authContext.isAuthenticated) {
navigate(ROUTER_PATHS.HOME);
}

if (authContext.userData.type === "student") {
navigate(ROUTER_PATHS.STUDENT_DASHBOARD);
}

console.log(authContext.userData.type)

if(authContext.userData.type !== "organiser"){
document.location = GH_OAUTH_ORG_URL;
}
}, [authContext]);

useEffect(() => {
fetch(`${BACKEND_URL}/project/all`, {
method: "GET",
headers: {
'Bearer' : `${authContext.jwt} `
}
}).then((res) => {
if(res.ok){
res.json().then((res:Project[]) => {
setAllData(res);
setFilterData(res.filter((item) => !item.status_remark));
setPgNo(1);
});
console.log(allData.length)
}
});
}, []);

useEffect(() => {
const startidx = (pgNo - 1) * PAGENATION_LEN;
const endidx = Math.min(startidx + PAGENATION_LEN, filterData.length);
setCurrPage(filterData.slice(startidx, endidx));
}, [pgNo, filterData]);

const showAll = () => {
const fItems = allData.filter((item) => !item.status_remark);
setFilterData(fItems);
setPgNo(1);
}

const showAccept = () => {
const fItems = allData.filter((item) => item.status_remark && item.project_status);
setFilterData(fItems);
setPgNo(1);
}

const showReject = () => {
const fItems = allData.filter((item) => item.status_remark && !item.project_status);
setFilterData(fItems);
setPgNo(1);
}

const nextPage = () => {
if(pgNo < filterData.length / PAGENATION_LEN) setPgNo(pgNo + 1);
}

const prevPage = () => {
if(pgNo >= 2) setPgNo(pgNo - 1);
}
return (
<div className='org-dash-main'>
<div className="org-dash-left">
<div className="org-dash-title">Mentor Projects</div>
<div className="org-dash-type-btn">
<div className="org-dash-btn-all">
<button onClick={() => showAll()}>Review</button>
</div>
<div className="org-dash-btn-accept">
<button onClick={() => showAccept()} className='approve-btn'>Approved</button>
</div>
<div className="org-dash-btn-rej">
<button onClick={() => showReject()} className='reject-btn'>Rejected</button>
</div>
</div>
<div className="org-dash-view">
<div className="org-dash-table-wrap">
<div className="org-dash-table">
{currPage.map((value) => (
<ListItem item={value}/>
))}
</div>
</div>
<div className="org-dash-table-nav">
<button className='org-dash-table-back' onClick={() => prevPage()}>&lt;</button>
<div className="org-dash-table-info">
Showing {(pgNo - 1) * PAGENATION_LEN + 1} - {Math.min(pgNo * PAGENATION_LEN, filterData.length)} of {filterData.length}
</div>
<button className='org-dash-table-next' onClick={() => nextPage()}>&gt;</button>
</div>
</div>
</div>
</div>
)
}

export default OrgDash
2 changes: 1 addition & 1 deletion src/pages/ProjectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function ProjectForm(props: { isEditing?: boolean }) {
navigate(ROUTER_PATHS.HOME);
} else if (!authContext.isRegistered) {
navigate(authContext.formLink);
} else if (authContext.userData.type !== "mentor") {
} else if (authContext.userData.type !== "mentor" && authContext.userData.type != "organiser") {
navigate(authContext.dashboardLink);
}
});
Expand Down
Loading