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
32 changes: 5 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,11 @@
Assignment 4 - Components
===
Jacquelyn Lopez

Due: October 4th, by 11:59 AM.
I was given an extension from the professor.

For this assignment you will re-implement the client side portion of *either* A2 or A3 using either React or Svelte components. If you choose A3 you only need to use components for the data display / updating; you can leave your login UI as is.
## Jackie's Art Museum Using React

[Svelte Tutorial](https://github.com/cs4241-21a/cs4241-21a.github.io/blob/main/using_svelte.md)
[React Tutorial](https://github.com/cs4241-21a/cs4241-21a.github.io/blob/main/using_react.md)
Glitch https://a4-jlopez-codes.glitch.me

This project can be implemented on any hosting service (Glitch, DigitalOcean, Heroku etc.), however, you must include all files in your GitHub repo so that the course staff can view them.

Deliverables
---

Do the following to complete this assignment:

1. Implement your project with the above requirements.
3. Test your project to make sure that when someone goes to your main page on Glitch/Heroku/etc., it displays correctly.
4. Ensure that your project has the proper naming scheme `a4-firstname-lastname` so we can find it.
5. Fork this repository and modify the README to the specifications below. Be sure to add *all* project files.
6. Create and submit a Pull Request to the original repo. Name the pull request using the following template: `a4-firstname-lastname`.

Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions)
---

## Your Web Application Title

your hosting link e.g. http://a4-charlieroberts.glitch.me

Include a very brief summary of your project here and what you changed / added to assignment #3. Briefly (3–4 sentences) answer the following question: did the new technology improve or hinder the development experience?

Unlike previous assignments, this assignment will be solely graded on whether or not you successfully complete it. Partial credit will be generously given.
I based off this assignment from A2 by implementing React. The easiest way for me to do it was using Glitch's already-made react template. I believe it was so much easier using react and it felt like I had to use a lot less code. Everything should work.
19 changes: 19 additions & 0 deletions components/router.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react";
import { Switch, Route, Router } from "wouter";
import Home from "../pages/home";
import About from "../pages/about";

/**
* The router is imported in app.jsx
*
* Our site just has two routes in it–Home and About
* Each one is defined as a component in /pages
* We use Switch to only render one route at a time https://github.com/molefrog/wouter#switch-
*/

export default () => (
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
);
37 changes: 37 additions & 0 deletions components/seo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from "react";
import SEO from "../seo.json";
import { Helmet } from 'react-helmet-async';

const Seo = () => {
// If url is set to 'glitch-default', we use the hostname for the current page
// Otherwise we use the value set in seo.json
const url = SEO.url === 'glitch-default' ? window.location.hostname : SEO.url

// React Helmet manages the content of the page head such as meta tags
// We use the async package https://github.com/staylor/react-helmet-async
return <Helmet>
<title>{SEO.title}</title>

<meta
name="description"
content={SEO.description}
/>
<meta name="robots" content="index,follow" />
<link rel="canonical" href={url} />
<meta property="og:title" content={SEO.title} />
<meta property="og:type" content="article" />
<meta property="og:url" content={url} />
<meta
property="og:description"
content={SEO.description}
/>
<meta
property="og:image"
content={SEO.image}
/>

<meta name="twitter:card" content="summary" />
</Helmet>
};

export default Seo;
22 changes: 22 additions & 0 deletions hooks/prefers-reduced-motion.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";

// User system can indicate reduced motion setting https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion

const query = "(prefers-reduced-motion: no-preference)";

export function usePrefersReducedMotion() {
const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(
!window.matchMedia(query).matches
);
React.useEffect(() => {
const mediaQueryList = window.matchMedia(query);
const listener = event => {
setPrefersReducedMotion(!event.matches);
};
mediaQueryList.addListener(listener);
return () => {
mediaQueryList.removeListener(listener);
};
}, []);
return prefersReducedMotion;
}
55 changes: 55 additions & 0 deletions hooks/wiggle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useState, useCallback } from "react";
import { useSpring } from "react-spring";
import { usePrefersReducedMotion } from "./prefers-reduced-motion";
// Heavily inspired by Josh Comeau: https://www.joshwcomeau.com/react/boop/ 💖

// Wiggle function accepts various parameters specifying properties for the animation
export function useWiggle({
x = 0,
y = 0,
rotation = 0,
scale = 1,
timing = 150,
springConfig = {
tension: 300,
friction: 10
}
}) {
// Accessibility setting from the user system indicating that they prefer to minimize motion
const prefersReducedMotion = usePrefersReducedMotion();

// Declare state variable isActive, set initially to false
const [isActive, setIsActive] = useState(false);

// We offload the actual animation to spring: https://www.react-spring.io/docs/hooks/use-spring
const style = useSpring({
transform: isActive
? `translate(${x}px, ${y}px) rotate(${rotation}deg) scale(${scale})`
: `translate(0px, 0px) rotate(0deg) scale(1)`,
config: springConfig
});

// Timing parameter determines how long the wiggle lasts using browser setTimeout function
// React useEffect function https://reactjs.org/docs/hooks-effect.html
React.useEffect(() => {
if (!isActive) {
return;
}
const timeoutId = window.setTimeout(() => {
setIsActive(false);
}, timing);
return () => {
window.clearTimeout(timeoutId);
};
}, [isActive]); // Continue wiggle until isActive is set false when timeout elapses

// Set wiggle to active when the triggering event occurs - will be set false when effect completes above
const trigger = useCallback(() => {
setIsActive(true);
}, []);

let appliedStyle = prefersReducedMotion ? {} : style;

// Return animation style effect and function to apply on trigger in page
return [appliedStyle, trigger];
}
34 changes: 34 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "glitch-hello-react",
"version": "0.0.5",
"description": "A simple React single page app, built with Vite and React.",
"scripts": {
"start": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-spring": "^9.4.5",
"wouter": "^2.7.4",
"react-helmet-async": "^1.3.0",
"@vitejs/plugin-react": "^1.3.2"
},
"devDependencies": {
"vite": "^2.4.4"
},
"browserslist": [
">0.2%",
"not dead"
],
"engines": {
"node": "12.x"
},
"repository": {
"url": "https://glitch.com/edit/#!/glitch-hello-react"
},
"glitch": {
"projectType": "generated_static"
}
}
33 changes: 33 additions & 0 deletions src/AppointForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, {useState} from 'react';

const FormTwo = (props) => {

const initAppoint = {id: null, studentID: '', name: '', appointment: ''};

const [appoint, setAppoint] = useState(initAppoint);

const handleChange = e => {
const {name, value} = e.target;
setAppoint({...appoint, [name]: value});
}

const handleSubmit = e => {
e.preventDefault();
if (appoint.studentID && appoint.name && appoint.appointment) {
handleChange(e, props.addAppoint(appoint));
}
}



return (
<form>
<input className="u-full-width" type="text" placeholder="Enter Student ID" value={appoint.studentID} name="studentID" onChange={handleChange} />
<input className="u-full-width1" type="text" placeholder="Enter Name" value={appoint.name} name="name" onChange={handleChange} />
<input className="u-full-width2" type="text" placeholder="Enter Appointment Date" value={appoint.appointment} name="appointment" onChange={handleChange} />
<button className="button-primary" type="submit" onClick={handleSubmit} >Add Appointment</button>
</form>
)
}

export default FormTwo;
32 changes: 32 additions & 0 deletions src/EditForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, {useState, useEffect} from 'react';

const FormOne = (props) => {

useEffect(() => {
setAppoint(props.currentAppoint)
}, [props])

const [appoint, setAppoint] = useState(props.currentAppoint);

const handleChange = e => {
const {name, value} = e.target;
setAppoint({...appoint, [name]: value});
}

const handleSubmit = e => {
e.preventDefault();
if (appoint.studentID && appoint.name && appoint.appointment) props.updateAppoint(appoint);
}

return (
<form>
<input className="u-full-width" type="text" value={appoint.studentID} placeholder="Enter Student ID" name="studentID" onChange={handleChange} />
<input className="u-full-width1" type="text" value={appoint.name} placeholder="Enter Name" name="name" onChange={handleChange} />
<input className="u-full-width2" type="text" value={appoint.appointment} placeholder="Enter Appointment Date" name="appointment" onChange={handleChange} />
<button className="button-primary" type="submit" onClick={handleSubmit} >Edit appointment</button>
<button type="submit" className="cancel" onClick={() => props.setEditing(false)} >Cancel</button>
</form>
)
}

export default FormOne;
43 changes: 43 additions & 0 deletions src/Table.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';

const UserTable = (props) => {
return (
<table>
<thead>
<tr>
<th>ID</th>
<th>Student ID #</th>
<th>Name</th>
<th>Appointment Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{ props.appoints.length > 0 ? (
props.appoints.map(appoint => {
const {id, studentID, name, appointment} = appoint;
return (
<tr key={id}>
<td>{id}</td>
<td>{studentID}</td>
<td>{name}</td>
<td>{appointment}</td>
<td>
<button className="button-primary2" onClick={() => props.deleteAppoint(id)}>Delete</button>
<button className="button-primary2" onClick={() => props.editAppoint(id, appoint)}>Edit</button>
</td>
</tr>
)
})
) : (
<tr>
<td colSpan={4}>No appointments made.</td>
</tr>
)
}
</tbody>
</table>
)
}

export default UserTable;
Loading