Skip to content

Commit

Permalink
Merge branch 'main' into lisas-routes
Browse files Browse the repository at this point in the history
  • Loading branch information
szkieb committed Aug 7, 2022
2 parents 3c2f858 + 035ec5b commit c808dd8
Show file tree
Hide file tree
Showing 10 changed files with 725 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Subheading: Poppins Semibold -> CSS class subheading

Tags: Poppins Semibold -> CSS class tag

Paragraph: Work Sans -> CSS applied to all <p>
Paragraph: Work Sans -> CSS applied to all <\p>

## Tailwind Colors

Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"react-router-dom": "^6.3.0"
},
"devDependencies": {
"@types/node": "^18.6.3",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.0.0",
Expand Down
119 changes: 119 additions & 0 deletions src/components/TaskForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { useState } from "react";
import { topicsDummies } from "../database/Dummies";
import {
CreateContext,
InitialTask,
initialTask,
yesterday,
} from "../database/TypesNConsts";

import { useTasks, useTasksDispatch, ACTIONS } from "./TasksContext";

export function TaskForm() {
const [error, SetError] = useState("");
const [userInput, SetUserInput] = useState<InitialTask>(initialTask);
const tasks = useTasks();
const dispatch = useTasksDispatch() as CreateContext;

function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
if (userInput.topic === "default") {
SetError("Please choose a topic");
} else {
dispatch({ type: ACTIONS.ADD_TASK, payload: { userInput: userInput } });
SetError("");
SetUserInput(initialTask);
const calendar = document.getElementById(
"deadline-calendar"
) as HTMLInputElement;
calendar.value = calendar.defaultValue;
}
}

return (
<>
<form onSubmit={handleSubmit} className="flex flex-col p-6 gap-6">
<input
required
type="text"
placeholder="Name*"
name="name"
value={userInput.name}
onChange={(event) => {
SetUserInput({ ...userInput, name: event.target.value });
}}
/>
<input
required
name="deadline"
value={JSON.stringify(userInput.deadline).slice(1, 11)}
onChange={(event) => {
SetUserInput({
...userInput,
deadline: new Date(event.target.value),
});
}}
// a little magic to prevent setting past deadline
min={JSON.stringify(yesterday).slice(1, 11)}
type="date"
/>
{error && <p className="error text-red-500 ">{error}</p>}
<select
name="Topic"
required
id="topic"
value={userInput.topic}
onMouseDown={() => {
SetError("");
}}
onChange={(event) => {
SetUserInput({ ...userInput, topic: event.target.value });
}}
>
<option disabled value="default">
(please select)
</option>
{topicsDummies.map((element, idx) => (
<option key={idx} value={element}>
{element}
</option>
))}
</select>

<textarea
placeholder="Description"
name="description"
value={userInput.description}
onChange={(event) => {
SetUserInput({ ...userInput, description: event.target.value });
}}
/>
<div className="flex justify-between">
<div
id="priorityInputAndLabel"
className="flex gap-2 -mt-6 items-center"
>
<input
id="priority"
type="checkbox"
name="priority"
onChange={(event) => {
SetUserInput({
...userInput,
priority: event.target.checked,
});
}}
/>
<label htmlFor="priority">High Priority</label>
</div>
<button
className="bg-primary p-6 rounded-xl w-24 h-2 flex items-center justify-center self-end justify-self-end "
type="submit"
>
Submit
</button>
</div>
</form>
</>
);
}
221 changes: 221 additions & 0 deletions src/components/TaskList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { useState } from "react";
import { topicsDummies } from "../database/Dummies";
import { TaskProp, Tasks, yesterday } from "../database/TypesNConsts";
import {
ACTIONS,
CreateContext,
useTasks,
useTasksDispatch,
} from "./TasksContext";

export function TaskList() {
const tasks = useTasks() as Tasks;

if (tasks == undefined || tasks == null) {
return <p>Oops, looks like you haven't added anything yet</p>;
}

return (
<ul>
{tasks.map((task) => (
<li
key={task.id}
className="flex w-1/2 p-4 border-slate-700 border-2 rounded-md justify-between items-center"
>
<TaskItem task={task} />
</li>
))}
</ul>
);
}

function TaskItem({ task }: TaskProp) {
// I will probably need these here
const dispatch = useTasksDispatch() as CreateContext;

const [taskNameInput, setTaskNameInput] = useState(task.name);
const [isEditing, setIsEditing] = useState(false);
const [unconfirmed, setUnconfirmed] = useState(false);

let taskContent;
let ConfirmationPrompt;

if (unconfirmed) {
ConfirmationPrompt = (
<div className="bg-secondary w-64 relative bottom-5 ">
<p>Do you really want to delete the task?</p>
<div className="flex flex-row justify-evenly">
<button
className="flex justify-center items-center bg-primary w-fit h-4 p-4 rounded-lg"
onClick={() => {
dispatch({ type: ACTIONS.DELETE, payload: { id: task.id } });
}}
>
Yes, delete
</button>
<button
className="flex justify-center items-center bg-primary w-fit h-4 p-4 rounded-lg"
onClick={() => {
setUnconfirmed(false);
}}
>
No, abort
</button>
</div>
</div>
);
} else {
ConfirmationPrompt = (
<>
<button className="delete" onClick={() => setUnconfirmed(true)}>
<svg
className="w-4 hover:scale-110 hover:fill-slate-500 active:fill-inherit "
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 512.021 512.021"
>
<g>
<path d="M301.258,256.01L502.645,54.645c12.501-12.501,12.501-32.769,0-45.269c-12.501-12.501-32.769-12.501-45.269,0l0,0 L256.01,210.762L54.645,9.376c-12.501-12.501-32.769-12.501-45.269,0s-12.501,32.769,0,45.269L210.762,256.01L9.376,457.376 c-12.501,12.501-12.501,32.769,0,45.269s32.769,12.501,45.269,0L256.01,301.258l201.365,201.387 c12.501,12.501,32.769,12.501,45.269,0c12.501-12.501,12.501-32.769,0-45.269L301.258,256.01z" />
</g>
</svg>
</button>
</>
);
}

if (isEditing) {
taskContent = (
<>
<input
type="text"
value={taskNameInput}
onChange={(event) => {
setTaskNameInput(event.target.value);
}}
/>

<button
className="flex justify-center items-center bg-primary w-2 h-4 p-4 rounded-lg"
onClick={() => {
dispatch({
type: ACTIONS.CHANGE_NAME,
payload: { id: task.id, name: taskNameInput },
});
setIsEditing(false);
}}
>
Save
</button>
<button
className="flex justify-center items-center bg-primary w-fit h-4 p-4 rounded-lg"
onClick={() => {
setTaskNameInput(task.name);
setIsEditing(false);
}}
>
Discard
</button>
</>
);
} else {
taskContent = (
<>
<input
type="text"
readOnly
value={task.name}
onFocus={() => setIsEditing(true)}
/>
</>
);
}
return (
<>
{taskContent}
<div className="flex hover:scale-110 hover:fill-slate-500 hover:text-slate-500 active:text-inherit active:fill-inherit">
<svg
id="calendar"
className="w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M19,2H18V1a1,1,0,0,0-2,0V2H8V1A1,1,0,0,0,6,1V2H5A5.006,5.006,0,0,0,0,7V19a5.006,5.006,0,0,0,5,5H19a5.006,5.006,0,0,0,5-5V7A5.006,5.006,0,0,0,19,2ZM2,7A3,3,0,0,1,5,4H19a3,3,0,0,1,3,3V8H2ZM19,22H5a3,3,0,0,1-3-3V10H22v9A3,3,0,0,1,19,22Z" />
<circle cx="12" cy="15" r="1.5" />
<circle cx="7" cy="15" r="1.5" />
<circle cx="17" cy="15" r="1.5" />
</svg>
<input
required
value={JSON.stringify(task.deadline).slice(1, 11)}
name="deadline"
onChange={(event) => {
dispatch({
type: ACTIONS.CHANGE_DEADLINE,
payload: {
id: task.id,
deadline: new Date(event.target.value),
},
});
}}
// a little magic to prevent setting past deadline
min={JSON.stringify(yesterday).slice(1, 11)}
type="date"
/>
</div>

<select
name="Topic"
required
value={task.topic}
onChange={(event) => {
dispatch({
type: ACTIONS.CHANGE_TOPIC,
payload: {
id: task.id,
topic: event.target.value,
},
});
}}
>
<option disabled>(please select)</option>
{topicsDummies.map((element, idx) => (
<option key={idx} value={element}>
{element}
</option>
))}
</select>

<div className="flex items-center gap-2">
<input
type="checkbox"
name="priority"
checked={task.priority}
onChange={() => {
dispatch({ type: ACTIONS.PRIORITY, payload: { id: task.id } });
}}
/>
<label className="text-slate-500 text-sm" htmlFor="priority">
Priority?
</label>
</div>

<div className="flex items-center gap-2">
<input
type="checkbox"
name="completed"
onChange={() => {
dispatch({ type: ACTIONS.COMPLETED, payload: { id: task.id } });
}}
/>
<label className="text-slate-500 text-sm" htmlFor="completed">
Done?
</label>
</div>

{ConfirmationPrompt}
</>
);
}
Loading

0 comments on commit c808dd8

Please sign in to comment.