progress-widgets
Version:
Progress Widget component for use with React.js and Next.js. Customize size, color and amount of sections. Bar, Meter, Pie and Symbol Widgets available.
210 lines (153 loc) • 7.44 kB
JavaScript
'use client'
import React, {useEffect} from 'react';
import { v4 as uuidv4 } from 'uuid';
import '../helpers/symbols.css'
export default function Pie(props) {
const [SymbolArray, setSymbolArray] = React.useState([])
const [SymbolMap, setSymbolMap] = React.useState([])
const [ColorArray, setColorArray] = React.useState([])
const [PercentArray, setPercentArray] = React.useState([])
const shape_states = {"shape_array": [SymbolArray, setSymbolArray], "shape_map": [SymbolMap, setSymbolMap]}
const sections = Math.ceil(100 / props.base_states["current_color"][0].length)
const base_color = "#ebebeb"
useEffect(() => {
if(shape_states["shape_map"][0].length > 0){
props.base_states["length_value"] = 100
props.base_states["current_position"][1](100)
}
}, [shape_states["shape_map"][0]])
useEffect(() => {
if(props.base_states["trigger"][0] && props.base_states["current_position"][0] > 0 && parseInt(props.base_states["trigger_amount"][0])){
parseInt(props.base_states["trigger_amount"][0]) > 0 ? show_circles(true) : props.base_states["trigger_amount"][1](null)
!parseInt(props.base_states["trigger_amount"][0]) ? props.base_states["trigger"][1](false) : null
}
}, [props.base_states["trigger"][0], props.base_states["current_position"][0], parseInt(props.base_states["trigger_amount"][0])])
useEffect(() => {
props.base_states["reset"][0] ? reset_circles() : null
}, [props.base_states["reset"][0]])
useEffect(() => {
shape_states["shape_map"][0].length < 1 ? display_circles() : null
}, [shape_states["shape_map"][0]])
function reset_circles(){
shape_states["shape_array"][1]([])
shape_states["shape_map"][1]([])
setPercentArray([])
setColorArray([])
props.base_states["length_value"] = 1
props.base_states["current_position"][1](100)
props.base_states["reset"][1](false)
}
function clear_circles(){
shape_states["shape_array"][1]([])
shape_states["shape_map"][1]([])
}
function display_circles(){
let i = 0
props.base_states["restart"][1](false)
clear_circles()
while(i < props.base_states["length_value"][0]){
show_circles(false, true)
i++
}
}
function create_circle(condition){
let color = base_color
let style = {}
let percent_array = PercentArray
let shape = ""
let extra = 0
let percent = 0
let gray_value = 0
let temp_value = 0
style["--size"] = get_size()
condition ? percent_array.length < 1 ? percent_array.push(parseInt(props.base_states["trigger_amount"][0])) : percent_array[percent_array.length-1] <= sections ? percent_array[percent_array.length-1] = percent_array[percent_array.length-1] + parseInt(props.base_states["trigger_amount"][0]) : percent_array.push(parseInt(props.base_states["trigger_amount"][0])) : null
for(let k=0; k<percent_array.length; k++){
if(percent_array[k] > sections && (k + 1) < percent_array.length){
extra = percent_array[k] - sections
percent_array[k] = sections
try{
percent_array[k+1] = percent_array[k+1] + extra
}catch{}
}
}
if(percent_array.length > props.base_states["current_color"][0].length){
percent_array = percent_array.slice(percent_array.length - props.base_states["current_color"][0].length)
percent_array[percent_array.length-1] = sections
}
if(percent_array[percent_array.length-1] > sections && percent_array.length < props.base_states["current_color"][0].length){
temp_value = percent_array[percent_array.length-1] - sections
percent_array[percent_array.length-1] = sections
percent_array.push(temp_value)
}
for(let i=0; i<percent_array.length; i++){
percent = percent + percent_array[i]
percent > sections * (i + 1) ? percent = sections * (i+1): null
if(percent_array[percent_array.length-1] > sections && percent_array.length < props.base_states["current_color"][0].length){
temp_value = percent_array[percent_array.length-1] - sections
percent_array[percent_array.length-1] = sections
percent_array.push(temp_value)
}
color = get_color(true, percent_array.length)[i]
i == 0 ? shape = color + " 0% " + percent + "%" : shape = shape + ", " + color + " 0% " + percent + "%"
}
for(let k=0; k<percent_array.length; k++){
gray_value = gray_value + percent_array[k]
gray_value > sections * (k + 1) ? gray_value = sections * (k + 1): null
}
shape = shape + ", " + base_color + " " + gray_value + "% 100%"
style["--shape"] = shape
!condition ? style["--shape"] = base_color + " 0% 100%, transparent 100% 100%" : null
percent_array.length > 0 && percent_array[0] != 0 ? setPercentArray(percent_array) : null
return (
<div>
<div className="circle_fill" style={style}>
</div>
</div>
)
}
function show_circles(condition, start = null){
let pos = props.base_states["current_position"][0]
let shown_arr = []
shown_arr.push(create_circle(condition))
const shape_map = shown_arr.map((name, index) => {
return {
obj: shown_arr[index],
key: uuidv4()
}
})
shape_states["shape_array"][1](shown_arr)
shape_states["shape_map"][1](shape_map)
condition ? pos = pos - 1 : null
props.base_states["current_position"][1](pos)
props.base_states["trigger"][1](false)
}
function get_color(check, spot){
let color_array = props.base_states["current_color"][0].slice(0, spot)
color_array.length < 1 && spot > 0 ? spot = 0 : null
setColorArray(ColorArray)
return color_array
}
function get_size(){
if(props.base_states["size"]){
return (props.base_states["size"] * 100).toString() + "px"
}
return "100px"
}
return(
<div className="grid grid-auto-rows grid-cols-1 place-items-center gap-12">
<div className="text-xl mb-24 grid place-items-center">
{props.base_states["title"]}
</div>
<div className="grid place-items-center ml-[10%]" style={{ gridTemplateColumns: 'repeat(' + props.base_states["length_value"][0] + ', 4px)'}}>
{shape_states["shape_map"][0] ? shape_states["shape_map"][0].map((result) => {
return(
<div key={result.key}>
{result.obj}
</div>
)
})
: null}
</div>
</div>
)
}