add arhived

This commit is contained in:
Romulus21
2022-01-18 19:07:54 +01:00
parent 4e0fa8d0e5
commit 021848b543
8 changed files with 63 additions and 34 deletions

View File

@@ -10,10 +10,10 @@ export default function ContextsProviders({children}) {
const [data, setData] = useLocalStorage('data', {})
const [user, setUser] = useUser(data, setData)
const {plants, addPlant, editPlant, removePlant, addAction, doneTask, history} = usePlants(data, setData)
const {plants, addPlant, editPlant, removePlant, addAction, doneTask, history, archivedEntries} = usePlants(data, setData)
return <UserContext.Provider value={[user, setUser]}>
<PlantsContext.Provider value={{plants, addPlant, editPlant, removePlant, addAction, doneTask, history}}>
<PlantsContext.Provider value={{plants, addPlant, editPlant, removePlant, addAction, doneTask, history, archivedEntries}}>
{children}
</PlantsContext.Provider>
</UserContext.Provider>

View File

@@ -1,5 +1,6 @@
import { useEffect, useState } from "preact/hooks"
import {route} from "preact-router";
import {actionId} from "../utilities/actions";
const usePlants = (data, setData) => {
const [plants, setPlants] = useState([])
@@ -42,32 +43,28 @@ const usePlants = (data, setData) => {
setData({...data, plants: plants})
}
const doneTask = (actionId) => {
const doneTask = (action) => {
let history = data.history ?? {}
history[actionId] = new Date()
setData({...data, history: history})
notifyMe()
history[action] = new Date()
let archived = data.archived ?? []
archived.push({
plantId: Number(action.split('-')[1]),
action: actionId(action.split('-')[0]),
time: (new Date()).toSQLDate()
})
setData({...data, history: history, archived: archived})
}
const history = () => data.history ?? {}
const notifyMe = () => {
if (!('Notification' in window)) {
alert('Ce navigateur ne prend pas en charge la notification de bureau')
} else if (Notification.permission === 'granted') {
// Si tout va bien, créons une notification
const notification = new Notification('Salut toi!')
} else if (Notification.permission !== 'denied') {
Notification.requestPermission().then((permission) => {
// Si l'utilisateur accepte, créons une notification
if (permission === 'granted') {
const notification = new Notification('Salut toi!')
}
})
}
const archivedEntries = (plantId) => {
let archived = data.archived ?? []
return archived.where('plantId', plantId)
}
return {plants, addPlant, editPlant, removePlant, addAction, doneTask, history}
return {plants, addPlant, editPlant, removePlant, addAction, doneTask, history, archivedEntries}
}
export default usePlants

View File

@@ -20,4 +20,14 @@ Date.prototype.toSQLDate = function() {
return `${this.getFullYear()}-${Number(this.getMonth() + 1).pad(2)}-${Number(this.getDate()).pad(2)}`
}
/**
* Filter array on a field common of the objects
* @param {string} field to filter
* @param {string} search to filter by
* @returns {*[]}
*/
Array.prototype.where = function(field, search) {
return this.filter(item => item[field] === search)
}
export default App;

View File

@@ -30,7 +30,7 @@ export const Home = () => {
</div>
<div className="w-full sticky bottom-5 flex justify-end">
<div onClick={() => setAddModal(true)}
className="rounded-full w-16 h-16 flex items-center justify-center cursor-pointer bg-green-800 hover-bg-green-900 text-white">
className="rounded-full shadow w-16 h-16 flex items-center justify-center cursor-pointer bg-green-800 hover-bg-green-900 text-white">
Add +
</div>
</div>

View File

@@ -9,24 +9,23 @@ import {getPicture, storePicture} from "../utilities/pictures"
import {EditSVG, PlusSVG} from "../components/SVG"
import {classNames} from "../utilities/classNames"
import {PlantForm} from "../components/Plants"
import {ACTION_TYPES, actionId} from "../utilities/actions"
const Plant = ({id}) => {
const [addModal, setAddModal] = useState(false)
const [editModal, setEditModal] = useState(false)
const [deleteModal, setDeleteModal] = useState(false)
const {plants, editPlant, removePlant, addAction, doneTask, history} = useContext(PlantsContext)
const {plants, editPlant, removePlant, addAction, doneTask, history, archivedEntries} = useContext(PlantsContext)
const [plant, setPlant] = useState({})
const archived = archivedEntries(Number(id))
const [actionForm, setActionForm] = useState({})
const [image, setImage] = useState(localStorage.getItem("image" + id) ?? '')
const pictureName = 'picture-' + id
const picture = useRef(null)
const action_types = ['watering', 'spraying', 'bathing']
useEffect(() => {
const plantFind = plants.find(plant => plant.id === Number(id))
console.log(plantFind, plantFind['indoor'])
setPlant(plantFind)
}, [])
@@ -38,7 +37,7 @@ const Plant = ({id}) => {
e.preventDefault()
e.stopPropagation()
if (!actionForm.action_type) {
actionForm.action_type = action_types[0]
actionForm.action_type = ACTION_TYPES[0]
}
addAction(plant, actionForm)
setAddModal(false)
@@ -78,14 +77,15 @@ const Plant = ({id}) => {
</div>
<div className="flex-1">
{plant.description && <p>{ plant.description }</p>}
{/*{plant.hasAttribute('indoor') && <p>{ plant.indoor ? 'Indoor' : 'Outdoor' }</p>}*/}
{plant.hasOwnProperty('indoor') && <span className="inline-block bg-green-500 text-white px-2 py-1 text-sm font-semibold rounded shadow my-2">{ plant.indoor ? 'Indoor' : 'Outdoor' }</span>}
{plant.spot && <p>Spot: <span className="font-bold">{ plant.spot }</span></p>}
</div>
</div>
<div>
<div className="flex items-center gap-2">
<h2>Actions</h2>
<SmallButton className="bg-blue-500 hover:bg-blue-700 mb-2 mt-5" onClick={() => setAddModal(true)}>
<SmallButton className="bg-blue-500 hover:bg-blue-700 mb-2 mt-5"
onClick={() => setAddModal(true)}>
<PlusSVG className="w-4 h-4" />
</SmallButton>
</div>
@@ -98,13 +98,17 @@ const Plant = ({id}) => {
}
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>
<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 font-bold">{action.action_type}</span>
{Number(action.frequency) === 0
? <span>when you want</span>
: <span> every {action.frequency} days</span>}
<span className="text-gray-500">last task {lastTask ? lastTask.toFrDate() : 'never'}</span>
{/*<span>{ archived.where('action', actionId(action.action_type)).length }</span>*/}
</div>
})}
</div>
@@ -114,7 +118,14 @@ const Plant = ({id}) => {
<ModalTitle>Add Action</ModalTitle>
<form onSubmit={handleSubmit}>
<SelectField name="action_type" className="mb-2 mt-5" value={actionForm.action_type} options={action_types} onChange={(e) => setActionForm({ ...actionForm, action_type: e.target.value })}>Name</SelectField>
<SelectField name="action_type"
className="mb-2 mt-5"
value={actionForm.action_type}
options={ACTION_TYPES}
onChange={(e) => setActionForm({ ...actionForm, action_type: e.target.value })}>
Name
</SelectField>
<InputField name="frequency"
className="mb-5"
type="number"
@@ -125,7 +136,8 @@ const Plant = ({id}) => {
</InputField>
<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">
<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">
Add
</Button>
</form>

View File

@@ -1,9 +1,10 @@
import { useContext, useEffect, useState } from "preact/hooks";
import { PageLayout } from "../components/PageLayout";
import { UserContext } from "../Contexts";
import {PlantsContext, UserContext} from "../Contexts";
export default function Profile() {
const [user, setUser] = useContext(UserContext)
const {plants} = useContext(PlantsContext)
const [darkMode, setDarkMode] = useState(false)
useEffect(() => {
@@ -29,5 +30,8 @@ export default function Profile() {
onChange={() => handleChangeDarkMode()} />
Dark Mode
</label>
<div className="mt-5">
{plants.length} Plants
</div>
</PageLayout>
}

6
src/utilities/actions.js Normal file
View File

@@ -0,0 +1,6 @@
export const ACTION_TYPES = ['watering', 'spraying', 'bathing']
export const actionId = (action) => {
return ACTION_TYPES.findIndex(item => item === action)
}