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

Redesign courses phase 1 #220

Merged
merged 1 commit into from
May 11, 2024
Merged
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
57 changes: 57 additions & 0 deletions client/src/components/2024/PageButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import styles from '../../styles/PageButton.css'

/**********************************************************************************************************************
--PageButton Component--

This is a component that adds a button to the DOM that when clicked, loads up another page inside a centered modal.
Requires proper css styling to work properly.
--I believe this will be implemented in a way that the css is loaded wheneber this component is used

PROPS:
className: as expected with HTML elements, provides a class for css styling the button
children: as expected with HTML elements, provides children for the added button
newPage: The page (as a react component) to load inside the modal


**********************************************************************************************************************/

export default class PageButton extends React.Component{
constructor(props){
super(props);
this.state={
viewForm: false
};

this.handleClick = this.handleClick.bind(this);
}

handleClick()
{

this.setState({
viewForm: !this.state.viewForm
})
}

render(){
return(
<>
<button onClick={this.handleClick} className={this.props.className}>{this.props.children}</button>

{this.state.viewForm &&
<>
<div className='backdrop' />
<div className='centeredModal'>
<div className='modalContents'>
<button onClick={this.handleClick} className='xButton'>X</button>
{this.props.newPage}
</div>
</div>
</>
}

</>
)
}
}
138 changes: 74 additions & 64 deletions client/src/pages/AddCourse.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import apiUtil from '../utils/apiUtil'
import { TailSpin } from 'react-loader-spinner'
import Notice from '../components/Notice'
import useCourse from "../hooks/useCourse";
import styles from '../styles/addcourse.css'

function AddCourse(props){
export default function AddCourse(props){

//Old things, not sure how much of this is needed
const [name, setName] = useState("")
const [description, setDescription] = useState("")
const [published, setPublished] = useState()
Expand All @@ -19,6 +22,73 @@ function AddCourse(props){
const navigate = useNavigate()
const dispatch = useDispatch()

class CreateForm extends React.Component {
constructor(props){
super(props);
this.state = {
name: '',
description: '',
published: 'off'
};

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCheck = this.handleCheck.bind(this);
}

// every time a text box is updated, it's react state is updated as well.
handleChange(event) {
const { name, value } = event.target;
this.setState({
[name]: value
});
}

handleCheck(event){
const {name, checked } = event.target;
this.setState({
[name]: checked
});
}

//input React states to authenticateUser function.
handleSubmit() {
event.preventDefault();
const newCourse = {
name: this.state.name,
description: this.state.description,
published: (this.state.published == "on") ? 1 : 0
}
postCourse(newCourse);
}

render(){
return(
<form onSubmit={this.handleSubmit}>
{/*Input fields: value mapped to React state through handleChange*/}
<input type="text" name="name"
value={this.state.name} onChange={this.handleChange}
className="inputContainer" placeholder="Class Name"
/>
<input type="text" name="description"
value={this.state.description} onChange={this.handleChange}
className="inputContainer" placeholder= "Class Description"
/>

<input type="checkbox" name="published"
checked={this.state.published} onChange={this.handleCheck}
className="publishedCheck"
/>
<label className='publishedLabel'> Publish course? </label>



<input type="submit" value="Create Course" className= "submitButton" />
</form>
)
}
}

async function postCourse(newCoursePayload){
//make a POST course api call
setLoading(true)
Expand All @@ -36,71 +106,11 @@ function AddCourse(props){
}
}

function addCourseSubmit(e){
e.preventDefault()

const newCourse = {
name: name,
description: description,
published: (published == "on") ? 1 : 0
}

postCourse(newCourse)
}

return (
<>
{ message !== "" && <Notice message={message} error={error}/> }
{ loading ? <TailSpin visible={true}/> : <Form className="create-container" onSubmit={(e) => { addCourseSubmit(e) }}>
<div className='create-bar'>
<Link className='back-btn-create' to={`/`}>
<Button className='back-btn'>
<div id="back-btn-image"/>
</Button>
</Link>
<p className='create-subtitle'>Create Course</p>
</div>

<hr className='create-hr-bar'></hr>

<Form.Group className="inputNameContainer">
<Form.Label>Class Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter Class Name"
onChange={(e) => setName(e.target.value)}/>
</Form.Group>
<Form.Group className="inputDescriptionContainer">
<Form.Label>Class Description</Form.Label>
<Form.Control
id="create-description"
as="textarea"
rows="4"
placeholder="Enter Class Description"
onChange={(e) => setDescription(e.target.value)}/>
</Form.Group>
{/*Publish Course Doesn't do anything yet - NOT FUNCTION*/}
<Form.Group className="inputPublishedContainer">
<Form.Check
type="switch"
id="publishSwitch"
label="Publish Class"
size="large"
onChange={(e) => setPublished(e.target.value)}/>
</Form.Group>
<div className="create-btns">
<Link to={`/`}>
<Button variant="secondary" id="create-cancel">
Cancel
</Button>
</Link>
<Button variant="primary" type="submit" id="create-submit">
Create Course
</Button>
</div>
</Form> }
<div className='createContainer'>
<CreateForm />
</div>
</>
)
}

export default AddCourse;
15 changes: 12 additions & 3 deletions client/src/pages/TeacherLanding.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { Button, Card } from "react-bootstrap"
import useCourses from '../hooks/useCourses'
import Notice from '../components/Notice'
import { Link } from 'react-router-dom';
import styles from '../styles/landing.css'
import AddCourse from './AddCourse.js'
import PageButton from '../components/2024/PageButton.js'


function TeacherLanding(props) {

Expand All @@ -16,13 +20,18 @@ function TeacherLanding(props) {

{/*Teacher Courses*/}
{courses.teacherCourses && <div id="teacher-courses">
<Link id="create-course-btn" to={`/createcourse`}>
<Button variant="primary" className='btn-add'>Create Course</Button>
</Link>
{/*<Link id="create-course-btn" to={`/createcourse`}>
<Button variant="primary" className='btn-add'>Create Course</Button>
</Link> */}



<p id="landing-subtitle">Instructor Courses</p>
<hr></hr>

<PageButton newPage={< AddCourse/>} className='createCourseButton'>
+ Create New </PageButton>

<div className='courses'>
{courses.teacherCourses.map((teacherCourse) => {
return <CourseCard key={teacherCourse.id} course={teacherCourse} role={"teacher"} />
Expand Down
50 changes: 50 additions & 0 deletions client/src/styles/PageButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.xButton
{
position: relative;
background: none;
border: none;
float: right;
top: 15px;
right: 30px;
}

.xButton:hover
{
background-color: red;
}

.backdrop
{
z-index: 2;

position: fixed;
top: 0px;
width: 100%;
height: 100%;

background-color: rgba(100, 100, 100, 0.5);
}

.centeredModal
{
z-index: 4;
position: fixed;
inset: 0px;
width: 50%;
height: 40%;
max-width: 100vw;
max-height: 100dvh;
margin: auto;
}

.modalContents
{
position:relative;
background-color: white;
height: 100%;
width: 100%;

border-width: 2px;
border-style: solid;
border-radius: 40px;
}
60 changes: 60 additions & 0 deletions client/src/styles/addcourse.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.backdrop
{
z-index: 2;

position: absolute;
top: 0px;
width: 100%;
height: 100%;

background-color: rgba(100, 100, 100, 0.5);
}

.createContainer
{
position: relative;
top: 15%;
left:50%;
transform: translateX(-50%);
width: 80%;
height: 80%;

display: flex;
justify-content: center;
align-items: center;
}

.inputContainer
{
margin-bottom: 20px;
background:transparent;
padding-left: 6px;
border:solid gray;
width: 100%;
}

.submitButton
{
margin-top: 5vh;

display: block;
position: relative;
left: 50%;
transform: translateX(-50%);
border: 1px solid var(--splash);
border-radius: 9px;
width: 256px;
height: 48px;
transition: 0.4s;
background-color: var(--splash);

&:hover {
border: 1px solid black;
background-color: var(--primary);
}
}

.publishedLabel
{
margin-left: 4px;
}
13 changes: 13 additions & 0 deletions client/src/styles/landing.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.createCourseButton
{
border-radius: 5px;
border-width: 1px;
background-color: var(--splash);

margin-left: 20px;

&:hover{
border: 1px solid black;
background-color: var(--primary);
}
}
Loading