change icon & edit plant
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 620 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -1,7 +1,6 @@
|
|||||||
import {classNames} from "../utilities/classNames";
|
import {classNames} from "../utilities/classNames";
|
||||||
|
|
||||||
|
export const InputField = ({children, name, value = "", type = "text", ...props}) => {
|
||||||
export const InputField = ({children, name, type = "text", ...props}) => {
|
|
||||||
|
|
||||||
const id = props.id ?? name
|
const id = props.id ?? name
|
||||||
const classStyle = props.className ?? ''
|
const classStyle = props.className ?? ''
|
||||||
@@ -17,6 +16,7 @@ export const InputField = ({children, name, type = "text", ...props}) => {
|
|||||||
<input id={id}
|
<input id={id}
|
||||||
name={name}
|
name={name}
|
||||||
type={type}
|
type={type}
|
||||||
|
value={value}
|
||||||
className="focus:ring-indigo-500 focus:border-indigo-500 block w-full px-2 py-1 mt-1 sm:text-sm border border-gray-300 rounded-md dark:bg-gray-500"
|
className="focus:ring-indigo-500 focus:border-indigo-500 block w-full px-2 py-1 mt-1 sm:text-sm border border-gray-300 rounded-md dark:bg-gray-500"
|
||||||
{...props}/>
|
{...props}/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|||||||
48
src/icon.svg
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
@@ -1,6 +1,10 @@
|
|||||||
import App from './components/App';
|
import App from './components/App';
|
||||||
import './style';
|
import './style';
|
||||||
|
|
||||||
|
Number.prototype.pad = function(n) {
|
||||||
|
return (new Array(n).join('0') + this).slice(-n)
|
||||||
|
}
|
||||||
|
|
||||||
Date.prototype.addDays = function (days) {
|
Date.prototype.addDays = function (days) {
|
||||||
let date = new Date(this.valueOf());
|
let date = new Date(this.valueOf());
|
||||||
date.setDate(date.getDate() + days);
|
date.setDate(date.getDate() + days);
|
||||||
@@ -12,4 +16,8 @@ Date.prototype.toFrDate = function() {
|
|||||||
return `${this.getDate()}/${month}/${this.getFullYear()}`
|
return `${this.getDate()}/${month}/${this.getFullYear()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Date.prototype.toSQLDate = function() {
|
||||||
|
return `${this.getFullYear()}-${Number(this.getMonth() + 1).pad(2)}-${Number(this.getDate()).pad(2)}`
|
||||||
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {Button, SmallButton} from "../components/Button"
|
|||||||
import {Modal, ModalTitle} from "../components/Modals"
|
import {Modal, ModalTitle} from "../components/Modals"
|
||||||
import { PageLayout } from "../components/PageLayout"
|
import { PageLayout } from "../components/PageLayout"
|
||||||
import { PlantsContext } from "../Contexts"
|
import { PlantsContext } from "../Contexts"
|
||||||
import {InputField, SelectField} from "../components/Form"
|
import {InputField, SelectField, TextAreaField} from "../components/Form"
|
||||||
import {getPicture, storePicture} from "../utilities/pictures"
|
import {getPicture, storePicture} from "../utilities/pictures"
|
||||||
import {EditSVG, PlusSVG} from "../components/SVG";
|
import {EditSVG, PlusSVG} from "../components/SVG";
|
||||||
import {classNames} from "../utilities/classNames";
|
import {classNames} from "../utilities/classNames";
|
||||||
@@ -12,7 +12,9 @@ import {classNames} from "../utilities/classNames";
|
|||||||
const Plant = ({id}) => {
|
const Plant = ({id}) => {
|
||||||
|
|
||||||
const [addModal, setAddModal] = useState(false)
|
const [addModal, setAddModal] = useState(false)
|
||||||
const {plants, removePlant, addAction, doneTask, history} = useContext(PlantsContext)
|
const [editModal, setEditModal] = useState(false)
|
||||||
|
const [plantForm, setPlantForm] = useState({})
|
||||||
|
const {plants, editPlant, removePlant, addAction, doneTask, history} = useContext(PlantsContext)
|
||||||
const [plant, setPlant] = useState({})
|
const [plant, setPlant] = useState({})
|
||||||
const [actionForm, setActionForm] = useState({})
|
const [actionForm, setActionForm] = useState({})
|
||||||
const [image, setImage] = useState(localStorage.getItem("image" + id) ?? '')
|
const [image, setImage] = useState(localStorage.getItem("image" + id) ?? '')
|
||||||
@@ -20,7 +22,6 @@ const Plant = ({id}) => {
|
|||||||
const picture = useRef(null)
|
const picture = useRef(null)
|
||||||
|
|
||||||
const action_types = ['watering', 'spraying', 'bathing']
|
const action_types = ['watering', 'spraying', 'bathing']
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const plantFind = plants.find(plant => plant.id === Number(id))
|
const plantFind = plants.find(plant => plant.id === Number(id))
|
||||||
@@ -41,30 +42,55 @@ const Plant = ({id}) => {
|
|||||||
setAddModal(false)
|
setAddModal(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleEditSubmit = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
editPlant(plantForm)
|
||||||
|
setEditModal(false)
|
||||||
|
setPlant(plantForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
const isCloseModal = e => e.target.classList.contains("overlay") || e.target.classList.contains("close-button")
|
||||||
|
|
||||||
const handleCloseAddModal = (e) => {
|
const handleCloseAddModal = (e) => {
|
||||||
if (e.target.classList.contains("overlay") || e.target.classList.contains("close-button")) {
|
if (isCloseModal(e)) {
|
||||||
setAddModal(false)
|
setAddModal(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleOpenEditModal = () => {
|
||||||
|
setEditModal(true)
|
||||||
|
console.log(plant)
|
||||||
|
setPlantForm(plant)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseEditModal = (e) => {
|
||||||
|
if (isCloseModal(e)) {
|
||||||
|
setEditModal(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const addPicture = e => storePicture(e, id)
|
const addPicture = e => storePicture(e, id)
|
||||||
|
|
||||||
return <PageLayout>
|
return <PageLayout>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<h1>{ plant.name }</h1>
|
<h1 className="my-2 flex-1 text-center">{ plant.name }</h1>
|
||||||
<div>
|
<div>
|
||||||
<Button className="bg-red-500" onClick={() => removePlant(plant)}>Delete</Button>
|
<Button className="bg-blue-500" onClick={() => handleOpenEditModal()}>Edit</Button>
|
||||||
|
{/*<Button className="bg-red-500" onClick={() => removePlant(plant)}>Delete</Button>*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>{ plant.description }</p>
|
<div className="flex justify-around flex-wrap gap-5">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<img id="picture" ref={picture} src={getPicture(id)} alt=""/>
|
<img id="picture" ref={picture} src={getPicture(id)} alt=""/>
|
||||||
<SmallButton className="absolute top-2 left-2 cursor-pointer bg-blue-500 hover:bg-blue-700 max-w-[300px]">
|
<SmallButton className="absolute top-2 left-2 cursor-pointer bg-blue-500 hover:bg-blue-700 max-w-[300px]">
|
||||||
<label className="relative">
|
<label className="relative">
|
||||||
<EditSVG className="w-4 h-4 block z-10 cursor-pointer" />
|
<EditSVG className="w-4 h-4 block z-10 cursor-pointer" />
|
||||||
<input id="input-file" type="file" name="picture" className="absolute opacity-0 max-w-[300px] w-0 h-0 inline" onChange={addPicture}/>
|
<input id="input-file" type="file" name="picture" className="absolute opacity-0 max-w-[300px] w-0 h-0 inline" onChange={addPicture}/>
|
||||||
</label>
|
</label>
|
||||||
</SmallButton>
|
</SmallButton>
|
||||||
|
</div>
|
||||||
|
<p className="flex-1">{ plant.description }</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -78,10 +104,12 @@ const Plant = ({id}) => {
|
|||||||
let lastTask = false
|
let lastTask = false
|
||||||
if (history()[action.id]) {
|
if (history()[action.id]) {
|
||||||
lastTask = new Date(history()[action.id])
|
lastTask = new Date(history()[action.id])
|
||||||
isDone = lastTask.addDays(Number(action.frequency)) < (new Date())
|
isDone = lastTask.addDays(Number(action.frequency)).toSQLDate() >= (new Date()).toSQLDate()
|
||||||
}
|
}
|
||||||
return <div key={action.action_type} className="flex items-center gap-2 my-2">
|
return <div key={action.action_type} className="flex items-center gap-2 my-2">
|
||||||
<span><Button className={classNames(isDone ? "bg-green-500 hover:bg-green-700" : "bg-blue-500 hover:bg-blue-700")} onClick={() => doneTask(action.id)}>Done</Button></span>
|
<span>
|
||||||
|
<Button className={classNames(isDone ? "bg-green-500 hover:bg-green-700" : "bg-blue-500 hover:bg-blue-700")} onClick={() => doneTask(action.id)}>Done</Button>
|
||||||
|
</span>
|
||||||
<span className="capitalize">{action.action_type}</span>
|
<span className="capitalize">{action.action_type}</span>
|
||||||
<span>every {action.frequency} days</span>
|
<span>every {action.frequency} days</span>
|
||||||
<span className="text-gray-500">last task {lastTask ? lastTask.toFrDate() : 'never'}</span>
|
<span className="text-gray-500">last task {lastTask ? lastTask.toFrDate() : 'never'}</span>
|
||||||
@@ -104,6 +132,24 @@ const Plant = ({id}) => {
|
|||||||
</Modal>,
|
</Modal>,
|
||||||
app
|
app
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{createPortal(
|
||||||
|
<Modal isOpen={editModal} onChange={handleCloseEditModal}>
|
||||||
|
<ModalTitle>
|
||||||
|
Edit Plant
|
||||||
|
</ModalTitle>
|
||||||
|
<form onSubmit={handleEditSubmit}>
|
||||||
|
|
||||||
|
<InputField name="name" className="mb-2 mt-5" value={plantForm.name} onChange={(e) => setPlantForm({ ...plantForm, name: e.target.value }) }>Name</InputField>
|
||||||
|
<TextAreaField name="description" className="mb-5" value={plantForm.description} onChange={(e) => setPlantForm({ ...plantForm, description: e.target.value })}>Description</TextAreaField>
|
||||||
|
|
||||||
|
<Button type="submit" className="block w-full mt-5 mb-2 bg-green-800 hover:bg-green-900 text-white mx-auto px-2 py-1 shadow">
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</Modal>,
|
||||||
|
app
|
||||||
|
)}
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||