Skip to content
This repository was archived by the owner on Jan 19, 2026. It is now read-only.

Commit 62d43e2

Browse files
committed
Added error messages
1 parent 2b5d89a commit 62d43e2

File tree

8 files changed

+177
-64
lines changed

8 files changed

+177
-64
lines changed

client/src/App.jsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import "./App.css"
22
import Button from "./components/Button"
3+
import ErrorAlert from "./components/errors/ErrorAlert"
34
import NewTaskForm from "./components/modals/NewTaskForm"
45
import Table from "./components/Table"
56
import { useEffect, useState } from "react"
@@ -9,16 +10,26 @@ export default function App() {
910
const [showModal, setShowModal] = useState(false);
1011
const [data, setData] = useState([]);
1112
const [loading, setLoading] = useState(true);
12-
13+
const [isError, setIsError] = useState(false);
14+
const [errorMessage, setErrorMessage] = useState("");
15+
1316
useEffect(() => {
1417
fetch(import.meta.env.VITE_SERVER_URL)
15-
.then((res) => res.json())
18+
.then((res) => {
19+
if(!res.ok){
20+
setIsError(true);
21+
setErrorMessage(`Error (${res.status}): ${res.statusText}`)
22+
}
23+
return res.json()
24+
}
25+
)
1626
.then((data) => {
1727
setData(data);
1828
setLoading(false);
1929
})
2030
.catch((error) => {
21-
console.error("Error fetching tasks:", error);
31+
setIsError(true);
32+
setErrorMessage(`Error (${error.name}): ${error.message}`);
2233
setLoading(false)
2334
})
2435
},[])
@@ -34,14 +45,18 @@ export default function App() {
3445
})
3546
.then(res=>{
3647
if(!res.ok){
37-
throw new Error(res.statusText + ": " + res.status);
48+
setIsError(true);
49+
setErrorMessage(`Error (${res.status}): ${res.statusText}`)
3850
}
3951
return res.json()
4052
})
4153
.then((data) => {
4254
setData(apiData => [...apiData, data])
4355
})
44-
.catch(error => console.log(error))
56+
.catch(error => {
57+
setIsError(true);
58+
setErrorMessage(`Error (${error.name}): ${error.message}`);
59+
})
4560
}
4661

4762
if (loading) return <p>Loading...</p>;
@@ -53,6 +68,9 @@ export default function App() {
5368
{showModal && (
5469
<NewTaskForm setShowModal={setShowModal} onAddTask={onAddTask}/>
5570
)}
71+
{isError && (
72+
<ErrorAlert onClick={() => setIsError(false)}>{errorMessage}</ErrorAlert>
73+
)}
5674
</>
5775
)
5876
}

client/src/assets/error-image.png

25.3 KB
Loading

client/src/components/Table.jsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { useReactTable, getCoreRowModel, flexRender } from '@tanstack/react-table'
2-
import { useEffect, useMemo, useState } from 'react'
2+
import { useMemo, useState } from 'react'
33
import "./Table.css"
44
import EditTaskForm from './modals/EditTaskForm';
55
import DeleteButton from './DeleteButton';
6+
import ErrorAlert from './errors/ErrorAlert';
67

78
export default function Table({data}) {
89

910
const [_tasks, setTasks] = useState(data);
1011
const [selectedTask, setSelectedTask] = useState(null);
11-
12+
const [isError, setIsError] = useState(false);
13+
const [errorMessage, setErrorMessage] = useState("");
14+
1215
const columns = useMemo(() => [
1316
{ header: '#', cell: info => info.row.index + 1},
1417
{ header: 'Estatus', accessorFn: row => row.status.percentage},
@@ -32,10 +35,14 @@ export default function Table({data}) {
3235
})
3336
.then(res => {
3437
if(!res.ok) {
35-
throw new Error(res.statusText);
38+
setIsError(true);
39+
setErrorMessage(`Error (${res.status}): ${res.statusText}`)
3640
}
3741
})
38-
.catch((error) => console.log(error))
42+
.catch((error) => {
43+
setIsError(true);
44+
setErrorMessage(`Error (${error.name}): ${error.message}`);
45+
})
3946

4047
}
4148

@@ -62,11 +69,16 @@ export default function Table({data}) {
6269
})
6370
.then(res => {
6471
if(!res.ok) {
65-
throw new Error(res.status)
72+
setIsError(true);
73+
setErrorMessage(`Error (${res.status}): ${res.statusText}`)
6674
}
75+
return res.json()
6776
})
6877
.then(data => console.log("Got data: ", data))
69-
.catch(error => console.error(error));
78+
.catch(error => {
79+
setIsError(true);
80+
setErrorMessage(`Error (${error.name}): ${error.message}`);
81+
});
7082

7183
setSelectedTask(null)
7284
}
@@ -106,6 +118,9 @@ export default function Table({data}) {
106118
onClose={() => setSelectedTask(null)}
107119
/>
108120
)}
121+
{isError && (
122+
<ErrorAlert onClick={() => setIsError(false)}>{errorMessage}</ErrorAlert>
123+
)}
109124
</>
110125
)
111126
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import styles from './ErrorAlert.module.css';
2+
import errorImage from '../../assets/error-image.png';
3+
4+
export default function ErrorAlert({onClick, children}) {
5+
return(
6+
<div className={styles["modal-overlay"]}>
7+
<div className={styles["modal"]}>
8+
<div className={styles["container"]}>
9+
<img width="10%" src={errorImage}/>
10+
<p>{children}</p>
11+
</div>
12+
<button className={styles["ok-button"]} onClick={onClick}>OK</button>
13+
</div>
14+
</div>
15+
)
16+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.modal-overlay {
2+
position: fixed;
3+
top: 0;
4+
left: 0;
5+
background: rgba(0,0,0,0.5);
6+
width: 100%;
7+
height: 100%;
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
z-index: 999;
12+
}
13+
14+
.modal {
15+
background-color: white;
16+
padding: 2rem;
17+
border-radius: 12px;
18+
width: 300px;
19+
box-shadow: 0 5px 20px rgba(0,0,0,0.3);
20+
max-width: 90%;
21+
}
22+
23+
.container {
24+
box-sizing: border-box;
25+
display: flex;
26+
align-items: center;
27+
}
28+
29+
.container p {
30+
margin-left: 20px;
31+
}
32+
33+
.ok-button {
34+
background-color: rgb(194, 28, 13);
35+
color: white;
36+
border: none;
37+
box-shadow: none;
38+
padding: 10px;
39+
font-weight: 600;
40+
font-size: small;
41+
border-radius: 10px;
42+
display: block;
43+
box-sizing: border-box;
44+
margin-top: 15px;
45+
}
Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { useState } from 'react'
22
import './EditTaskForm.css'
33
import Button from '../Button'
4+
import ErrorAlert from '../errors/ErrorAlert';
45

56
export default function EditTaskForm({task, onSave, onClose}) {
67
const [percentage, setPercentage] = useState(task.status.percentage);
78
const [label, setLabel] = useState(task.status.label);
89
const [description, setDescription] = useState(task.description);
910
const [asignee, setAsignee] = useState(task.asignee);
10-
1111
const [selectStyle, setSelectStyle] = useState(task.status.label === "EN PROCESO" ? {backgroundColor: "yellow", color: "darkorange"} : {backgroundColor: "lightgreen", color: "darkgreen"});
12+
const [isError, setIsError] = useState(false);
13+
const [errorMessage, setErrorMessage] = useState("");
1214

1315
function handleSelect(e) {
1416
if(e.target.value === "EN PROCESO"){
@@ -24,7 +26,8 @@ export default function EditTaskForm({task, onSave, onClose}) {
2426
function handleSubmit(e) {
2527
e.preventDefault();
2628
if([label, description, asignee].some(field => !field)) {
27-
console.log("Please enter all values")
29+
setIsError(true);
30+
setErrorMessage("Error (No Empty Values): Please fill out all the fields");
2831
return;
2932
}
3033

@@ -43,36 +46,42 @@ export default function EditTaskForm({task, onSave, onClose}) {
4346
}
4447

4548
return (
46-
<div className='modal-overlay'>
47-
<div className='modal'>
48-
<form>
49-
<label htmlFor="percentage-input">Porcentaje: (0-100)</label>
50-
<input value={percentage} onChange= {(e) => setPercentage(e.target.value)}id="percentage-input" type="number" placeholder="(0-100)"/>
49+
<>
50+
51+
<div className='modal-overlay'>
52+
<div className='modal'>
53+
<form>
54+
<label htmlFor="percentage-input">Porcentaje: (0-100)</label>
55+
<input value={percentage} onChange= {(e) => setPercentage(e.target.value)}id="percentage-input" type="number" placeholder="(0-100)"/>
5156

52-
<br/>
57+
<br/>
5358

54-
<label htmlFor="status-select">Estatus: </label>
55-
<select value={label} onChange={handleSelect} style={selectStyle} id="status-select">
56-
<option style={{backgroundColor: "yellow", color: "darkorange"}} value="EN PROCESO">EN PROCESO</option>
57-
<option style={{backgroundColor: "lightgreen", color: "darkgreen"}} value="COMPLETADO">COMPLETADO</option>
58-
</select>
59+
<label htmlFor="status-select">Estatus: </label>
60+
<select value={label} onChange={handleSelect} style={selectStyle} id="status-select">
61+
<option style={{backgroundColor: "yellow", color: "darkorange"}} value="EN PROCESO">EN PROCESO</option>
62+
<option style={{backgroundColor: "lightgreen", color: "darkgreen"}} value="COMPLETADO">COMPLETADO</option>
63+
</select>
5964

60-
<br/>
65+
<br/>
6166

62-
<label htmlFor="description-textarea">Descripción: </label>
63-
<textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={10} id="description-textarea" placeholder='Descripción'></textarea>
64-
65-
<br/>
67+
<label htmlFor="description-textarea">Descripción: </label>
68+
<textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={10} id="description-textarea" placeholder='Descripción'></textarea>
69+
70+
<br/>
6671

67-
<label htmlFor="asignee-input">Asignee: </label>
68-
<input value={asignee} onChange={(e) => setAsignee(e.target.value)} id = "asignee-input" type='text'/>
72+
<label htmlFor="asignee-input">Asignee: </label>
73+
<input value={asignee} onChange={(e) => setAsignee(e.target.value)} id = "asignee-input" type='text'/>
6974

70-
<div className='control-buttons'>
71-
<Button type="submit" fn={handleSubmit} text="Guardar Cambios"/>
72-
<Button fn={onClose} text="Cancelar"/>
73-
</div>
74-
</form>
75+
<div className='control-buttons'>
76+
<Button type="submit" fn={handleSubmit} text="Guardar Cambios"/>
77+
<Button fn={onClose} text="Cancelar"/>
78+
</div>
79+
</form>
80+
</div>
7581
</div>
76-
</div>
82+
{isError && (
83+
<ErrorAlert onClick={() => setIsError(false)}>{errorMessage}</ErrorAlert>
84+
)}
85+
</>
7786
)
7887
}
Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { useEffect, useState } from 'react'
22
import './NewTaskForm.css'
33
import Button from '../Button'
4+
import ErrorAlert from '../errors/ErrorAlert';
45

56
export default function NewTaskForm({setShowModal, onAddTask}) {
67

78
const [percentage, setPercentage] = useState(0);
89
const [label, setLabel] = useState("EN PROCESO");
910
const [description, setDescription] = useState("");
1011
const [asignee, setAsignee] = useState("");
11-
12+
const [isError, setIsError] = useState(false);
13+
const [errorMessage, setErrorMessage] = useState("");
1214
const [selectStyle, setSelectStyle] = useState({backgroundColor: "yellow", color: "darkorange"});
1315

1416
function handleSelect(e) {
@@ -27,7 +29,8 @@ export default function NewTaskForm({setShowModal, onAddTask}) {
2729

2830
console.log(percentage + " " + label + " " + description + " " + asignee)
2931
if([label, description, asignee].some(field => !field)) {
30-
console.log("Please enter all values")
32+
setIsError(true);
33+
setErrorMessage("Error (No Empty Values): Please fill out all the fields");
3134
return;
3235
}
3336

@@ -50,36 +53,41 @@ export default function NewTaskForm({setShowModal, onAddTask}) {
5053
}
5154

5255
return (
53-
<div className='modal-overlay'>
54-
<div className='modal'>
55-
<form>
56-
<label htmlFor="percentage-input">Porcentaje: (0-100)</label>
57-
<input value={percentage} onChange= {(e) => setPercentage(e.target.value)}id="percentage-input" type="number" placeholder="(0-100)"/>
56+
<>
57+
<div className='modal-overlay'>
58+
<div className='modal'>
59+
<form>
60+
<label htmlFor="percentage-input">Porcentaje: (0-100)</label>
61+
<input value={percentage} onChange= {(e) => setPercentage(e.target.value)}id="percentage-input" type="number" placeholder="(0-100)"/>
5862

59-
<br/>
63+
<br/>
6064

61-
<label htmlFor="status-select">Estatus: </label>
62-
<select value={label} onChange={handleSelect} style={selectStyle} id="status-select">
63-
<option style={{backgroundColor: "yellow", color: "darkorange"}} value="EN PROCESO">EN PROCESO</option>
64-
<option style={{backgroundColor: "lightgreen", color: "darkgreen"}} value="COMPLETADO">COMPLETADO</option>
65-
</select>
65+
<label htmlFor="status-select">Estatus: </label>
66+
<select value={label} onChange={handleSelect} style={selectStyle} id="status-select">
67+
<option style={{backgroundColor: "yellow", color: "darkorange"}} value="EN PROCESO">EN PROCESO</option>
68+
<option style={{backgroundColor: "lightgreen", color: "darkgreen"}} value="COMPLETADO">COMPLETADO</option>
69+
</select>
6670

67-
<br/>
71+
<br/>
6872

69-
<label htmlFor="description-textarea">Descripción: </label>
70-
<textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={10} id="description-textarea" placeholder='Descripción'></textarea>
71-
72-
<br/>
73+
<label htmlFor="description-textarea">Descripción: </label>
74+
<textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={10} id="description-textarea" placeholder='Descripción'></textarea>
75+
76+
<br/>
7377

74-
<label htmlFor="asignee-input">Asignee: </label>
75-
<input value={asignee} onChange={(e) => setAsignee(e.target.value)} id = "asignee-input" type='text'/>
78+
<label htmlFor="asignee-input">Asignee: </label>
79+
<input value={asignee} onChange={(e) => setAsignee(e.target.value)} id = "asignee-input" type='text'/>
7680

77-
<div className='control-buttons'>
78-
<Button type="submit" fn={handleSubmit} text="+ Agregar Tarea"/>
79-
<Button fn={handleCancel} text="Cancelar"/>
80-
</div>
81-
</form>
81+
<div className='control-buttons'>
82+
<Button type="submit" fn={handleSubmit} text="+ Agregar Tarea"/>
83+
<Button fn={handleCancel} text="Cancelar"/>
84+
</div>
85+
</form>
86+
</div>
8287
</div>
83-
</div>
88+
{isError && (
89+
<ErrorAlert onClick={() => setIsError(false)}>{errorMessage}</ErrorAlert>
90+
)}
91+
</>
8492
)
8593
}

0 commit comments

Comments
 (0)