|
|
|
@ -17,7 +17,8 @@ import Spinner from 'react-bootstrap/Spinner'; |
|
|
|
|
import Form from 'react-bootstrap/Form'; |
|
|
|
|
|
|
|
|
|
import { FaCheckCircle } from 'react-icons/fa'; |
|
|
|
|
import { IoCheckmarkCircleOutline,IoCloseCircleSharp,IoAlertCircleOutline } from 'react-icons/io5'; |
|
|
|
|
import { BiAlarmAdd } from 'react-icons/bi'; |
|
|
|
|
import { MdAlarmOff } from 'react-icons/md'; |
|
|
|
|
|
|
|
|
|
const fuzzysort = require('fuzzysort') |
|
|
|
|
|
|
|
|
@ -37,8 +38,36 @@ const progress2 = new Audio(process.env.PUBLIC_URL+"/progress2.mp3") |
|
|
|
|
const retainerNames = ["Ayayayaya","Kittystorage","Morecatz","Finalretainer","Nowitsabun","Butwhy","Kkittyy","Howdoesanyonenameall","Ayayayayay"]; |
|
|
|
|
|
|
|
|
|
function Item(p){ |
|
|
|
|
const {item,setLockout,contributor,lockout,itemCount,totalItemCount,playerInventory} = p |
|
|
|
|
const {item,contributor,itemCount,totalItemCount,playerInventory} = p |
|
|
|
|
const [itemLoc,setItemLoc]=useState("") |
|
|
|
|
const [itemTimers,setItemTimers]=useState([]) |
|
|
|
|
const [lockout,setLockout]=useState(false) |
|
|
|
|
|
|
|
|
|
function updateTimer(ts,te,timerIndex) { |
|
|
|
|
var newTimerStart=[]; |
|
|
|
|
if (item.timer_start!==null){ |
|
|
|
|
newTimerStart=[...item.timer_start.split(",")]; |
|
|
|
|
} |
|
|
|
|
var newTimerEnd=[]; |
|
|
|
|
if (item.timer_end!==null){ |
|
|
|
|
newTimerEnd=[...item.timer_end.split(",")]; |
|
|
|
|
} |
|
|
|
|
if (ts==""&&te==""){ |
|
|
|
|
newTimerStart=newTimerStart.filter((item,i)=>i!=timerIndex); |
|
|
|
|
newTimerEnd=newTimerEnd.filter((item,i)=>i!=timerIndex); |
|
|
|
|
} else { |
|
|
|
|
newTimerStart[timerIndex]=ts; |
|
|
|
|
newTimerEnd[timerIndex]=te; |
|
|
|
|
} |
|
|
|
|
setLockout(true) |
|
|
|
|
axios.post(BACKEND_URL+"/updateTimer",{timer_start:newTimerStart.join(","),timer_end:newTimerEnd.join(","),id:item.id,last_modified:new Date()}) |
|
|
|
|
.then((data)=>{ |
|
|
|
|
setLockout(false) |
|
|
|
|
}) |
|
|
|
|
.catch((err)=>{ |
|
|
|
|
setLockout(false) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function updateItem(item,target,contributor) { |
|
|
|
|
var correctedVal=Math.min(item.required,target.value); |
|
|
|
@ -49,7 +78,7 @@ function Item(p){ |
|
|
|
|
setLockout(false) |
|
|
|
|
}) |
|
|
|
|
.catch((err)=>{ |
|
|
|
|
|
|
|
|
|
setLockout(false) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -131,7 +160,7 @@ function Item(p){ |
|
|
|
|
tempItem.amt+=it.amt |
|
|
|
|
} |
|
|
|
|
tempItem.page=Math.floor(j/35+1) |
|
|
|
|
locObj[String(retainerNames[i-1])]={...tempItem} |
|
|
|
|
locObj[String(retainerNames[i-1])]={...tempItem} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -145,6 +174,12 @@ function Item(p){ |
|
|
|
|
//locs+="Player Inventory ["+Math.floor((j/35+1))+"] x"+it.amt
|
|
|
|
|
} |
|
|
|
|
setItemLoc(locs) |
|
|
|
|
if (item.required!==item.obtained&&item.timer_start!==null&&item.timer_start.length>0&&item.timer_start[0]!=""){ |
|
|
|
|
var endTimers = item.timer_end.split(","); |
|
|
|
|
setItemTimers(item.timer_start.split(",").map((t,i)=>{return {timer_start:t,timer_end:endTimers[i]}})) |
|
|
|
|
} else { |
|
|
|
|
setItemTimers([]) |
|
|
|
|
} |
|
|
|
|
},[item,playerInventory]) |
|
|
|
|
|
|
|
|
|
return <Row className={"pb-1 pt-1 text-light"+(Number(item.obtained)===0?item.finalcraft?" finalProduct":" notStarted":Number(item.obtained)===Number(item.required)?" completed":" inProgress")}> |
|
|
|
@ -164,12 +199,35 @@ function Item(p){ |
|
|
|
|
updateItem(item,{value:item.required},contributor) |
|
|
|
|
}}/>} |
|
|
|
|
</Col> |
|
|
|
|
<Col> |
|
|
|
|
{item.required!==item.obtained&&<> |
|
|
|
|
<Col sm={2}> |
|
|
|
|
<a style={{position:"relative",top:"8px"}} className="text-muted" href={"https://garlandtools.org/db/#item/"+item.itemid} target="tools">View Item Info</a> |
|
|
|
|
</Col> |
|
|
|
|
<Col sm={1}> |
|
|
|
|
<BiAlarmAdd style={{cursor:"pointer",borderBottom:"1px dotted",color:"#99FF99"}} onClick={()=>{if (item.timer_start!==null&&item.timer_start.length>0){updateTimer("0:00","3:00",item.timer_start.split(",").length)} else {updateTimer("0:00","3:00",0)}}}/> |
|
|
|
|
</Col> |
|
|
|
|
<Col sm={3}> |
|
|
|
|
{itemTimers.map((timer,i)=><Timer key={i} lockout={lockout} updateTimer={updateTimer} timerIndex={i} timer_start={timer.timer_start} timer_end={timer.timer_end}/>)} |
|
|
|
|
</Col></>} |
|
|
|
|
</Row> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function Timer(p){ |
|
|
|
|
const {timer_start,timer_end,timerIndex,updateTimer,lockout}=p |
|
|
|
|
const [timerStart,setTimerStart] = useState("") |
|
|
|
|
const [timerEnd,setTimerEnd] = useState("") |
|
|
|
|
useEffect(()=>{ |
|
|
|
|
setTimerStart(timer_start) |
|
|
|
|
setTimerEnd(timer_end) |
|
|
|
|
},[timer_start,timer_end]) |
|
|
|
|
return <Row> |
|
|
|
|
<Col sm={3}><DarkInput style={{width:"100%"}} disabled={lockout} value={timerStart} onChange={(f)=>{setTimerStart(f.currentTarget.value)}} onKeyDown={(k)=>{if (k.key==='Enter') {if (k.currentTarget.value!=timer_start){updateTimer(k.currentTarget.value,timer_end,timerIndex)}}}} onBlur={(f)=>{if (f.currentTarget.value!=timer_start){updateTimer(f.currentTarget.value,timer_end,timerIndex)}}}></DarkInput></Col> |
|
|
|
|
<Col sm={1} className="text-white">-</Col> |
|
|
|
|
<Col sm={3}><DarkInput style={{width:"100%"}} disabled={lockout} value={timerEnd} onChange={(f)=>{setTimerEnd(f.currentTarget.value)}} onKeyDown={(k)=>{if (k.key==='Enter') {if (k.currentTarget.value!=timer_end){updateTimer(timer_start,k.currentTarget.value,timerIndex)}}}} onBlur={(f)=>{if (f.currentTarget.value!=timer_end){updateTimer(timer_start,f.currentTarget.value,timerIndex)}}}></DarkInput></Col> |
|
|
|
|
<Col sm={1}><MdAlarmOff style={{cursor:"pointer",color:"red"}} onClick={(f)=>{updateTimer("","",timerIndex)}}/></Col> |
|
|
|
|
</Row> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function ItemGroup(p) { |
|
|
|
|
const { data } = p |
|
|
|
|
const { contributor,itemCount,totalItemCount,playerInventory,lockout,setLockout } = p |
|
|
|
@ -472,6 +530,32 @@ function ListApp(p){ |
|
|
|
|
</> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function TimeDisplay(duration){ |
|
|
|
|
var hrs=Math.floor(duration/3600) |
|
|
|
|
var min=Math.floor(duration/60)%60 |
|
|
|
|
return (hrs>0?hrs+" hrs,":"")+min+" min" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function TimerDisplay(p){ |
|
|
|
|
const {timer,eorzeanTime} = p |
|
|
|
|
var eorzeanSeconds=Number(eorzeanTime.split(":")[0])*3600+Number(eorzeanTime.split(":")[1])*60 |
|
|
|
|
return <><Row> |
|
|
|
|
<Col> |
|
|
|
|
<img src={"https://xivapi.com"+timer.icon}/> {timer.name} <sub><i style={{color:"gray"}}>{eorzeanSeconds>timer.actual_seconds&&eorzeanSeconds<timer.end_seconds?"Node Available: "+TimeDisplay(timer.end_seconds-eorzeanSeconds):TimeDisplay((eorzeanSeconds>timer.actual_seconds)?timer.actual_seconds+86400-eorzeanSeconds:timer.actual_seconds-eorzeanSeconds)}</i></sub> |
|
|
|
|
</Col> |
|
|
|
|
<Col> |
|
|
|
|
<span style={{float:"right"}}>{timer.timer_start} - {timer.timer_end}</span> |
|
|
|
|
</Col> |
|
|
|
|
</Row> |
|
|
|
|
<Row> |
|
|
|
|
<Col sm={1}/> |
|
|
|
|
<Col sm={10}> |
|
|
|
|
<ProgressBar variant={eorzeanSeconds>timer.actual_seconds&&eorzeanSeconds<timer.end_seconds?"success":""} animated={eorzeanSeconds>timer.actual_seconds&&eorzeanSeconds<timer.end_seconds} striped={eorzeanSeconds>timer.actual_seconds&&eorzeanSeconds<timer.end_seconds} now={eorzeanSeconds>timer.actual_seconds?eorzeanSeconds<timer.end_seconds?100-((eorzeanSeconds-timer.end_seconds)/(timer.seconds-timer.end_seconds))*100:((eorzeanSeconds-timer.actual_seconds)/864):(100-(timer.actual_seconds-eorzeanSeconds)/864)}></ProgressBar> |
|
|
|
|
</Col> |
|
|
|
|
</Row> |
|
|
|
|
</> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function App() { |
|
|
|
|
|
|
|
|
|
const [data,setData] = useState([]) |
|
|
|
@ -493,6 +577,10 @@ function App() { |
|
|
|
|
const [lastModified,setLastModified] = useState(new Date()) |
|
|
|
|
const [lastUpdate,setLastUpdate] = useState(0) |
|
|
|
|
const [playerInventory,setPlayerInventory] = useState([]) |
|
|
|
|
const [eorzeanTime,setEorzeanTime] = useState("") |
|
|
|
|
const [timerList,setTimerList] = useState([]) |
|
|
|
|
const [timerCutList1,setTimerCutList1] = useState([]) |
|
|
|
|
const [timerCutList2,setTimerCutList2] = useState([]) |
|
|
|
|
|
|
|
|
|
const [contributor,setContributor] = useState("") |
|
|
|
|
const [notifications,setNotifications] = useState([]) |
|
|
|
@ -503,11 +591,25 @@ function App() { |
|
|
|
|
|
|
|
|
|
const [matchedItems,setMatchedItems] = useState([]) |
|
|
|
|
|
|
|
|
|
const [lockout,setLockout] = useState(false) |
|
|
|
|
//const [lockout,setLockout] = useState(false)
|
|
|
|
|
|
|
|
|
|
function LZ(digits,numb) { |
|
|
|
|
return "0".repeat(digits-String(numb).length)+numb |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
|
var eorzeanSeconds=Number(eorzeanTime.split(":")[0])*3600+Number(eorzeanTime.split(":")[1])*60 |
|
|
|
|
var timerObjs=timerList.map((item)=>{ |
|
|
|
|
var seconds=Number(item.timer_start.split(":")[0])*3600+Number(item.timer_start.split(":")[1])*60 |
|
|
|
|
var originalSeconds=seconds |
|
|
|
|
var endSeconds=Number(item.timer_end.split(":")[0])*3600+Number(item.timer_end.split(":")[1])*60 |
|
|
|
|
if (endSeconds<seconds&&eorzeanSeconds>=0&&eorzeanSeconds<seconds){ |
|
|
|
|
seconds=0 |
|
|
|
|
} |
|
|
|
|
return {seconds:seconds,actual_seconds:originalSeconds,end_seconds:endSeconds,...item}}).sort((a,b)=>a.end_seconds-b.end_seconds) |
|
|
|
|
setTimerCutList1(timerObjs.filter((timer)=>timer.end_seconds>=eorzeanSeconds)) |
|
|
|
|
setTimerCutList2(timerObjs.filter((timer)=>timer.end_seconds<eorzeanSeconds)) |
|
|
|
|
},[timerList,eorzeanTime]) |
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
|
const interval = setInterval(()=>{ |
|
|
|
@ -519,6 +621,20 @@ function App() { |
|
|
|
|
return axios.get("https://projectdivar.com:4505/getData") |
|
|
|
|
.then((data)=>{ |
|
|
|
|
//setData(data.data)
|
|
|
|
|
var timers=[] |
|
|
|
|
var timerItems=data.data.filter((item)=>item.obtained!=item.required&&item.timer_start!=null&&item.timer_start.length>0) |
|
|
|
|
for (item of timerItems){ |
|
|
|
|
var splitter=item.timer_start.split(",") |
|
|
|
|
var splitter2=item.timer_end.split(",") |
|
|
|
|
var i=0 |
|
|
|
|
for (var t of splitter){ |
|
|
|
|
var newItem={...item} |
|
|
|
|
newItem.timer_start=t |
|
|
|
|
newItem.timer_end=splitter2[i++] |
|
|
|
|
timers=[...timers,newItem] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
setTimerList(timers) |
|
|
|
|
setData(data.data.slice(dataSplitters[0],dataSplitters[1])) |
|
|
|
|
setData2(data.data.slice(dataSplitters[1],dataSplitters[2])) |
|
|
|
|
setData3(data.data.slice(dataSplitters[2],dataSplitters[3])) |
|
|
|
@ -577,6 +693,22 @@ function App() { |
|
|
|
|
return ()=>clearInterval(interval) |
|
|
|
|
},[nav,lastUpdate]) |
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
|
const interval = setInterval(()=>{ |
|
|
|
|
if (nav==="main"){ |
|
|
|
|
var date=new Date() |
|
|
|
|
var earthH=date.getHours(),earthM=date.getMinutes(),earthS=date.getSeconds() |
|
|
|
|
var earthTime=earthH*3600+earthM*60+earthS |
|
|
|
|
var eorzeanTime=earthTime*20.571428571428571428571428571429 |
|
|
|
|
var eorzeanH=Math.floor(eorzeanTime/3600)%24 |
|
|
|
|
var eorzeanM=Math.floor(eorzeanTime/60)%60 |
|
|
|
|
var eorzeanS=Math.floor(eorzeanTime)%60 |
|
|
|
|
setEorzeanTime((("0")+eorzeanH).slice(-2)+":"+(("0")+eorzeanM).slice(-2)) |
|
|
|
|
} |
|
|
|
|
},3000) |
|
|
|
|
return ()=>clearInterval(interval) |
|
|
|
|
},[nav,lastUpdate]) |
|
|
|
|
|
|
|
|
|
useEffect(()=>{ |
|
|
|
|
var notificationLastUpdate = new Date(new Date()-(NOTIFICATIONTIMEOUT*1000)) |
|
|
|
|
var largestNotificationID = -1 |
|
|
|
@ -627,6 +759,20 @@ function App() { |
|
|
|
|
axios.get("https://projectdivar.com:4505/getData") |
|
|
|
|
.then((data)=>{ |
|
|
|
|
//setData(data.data)
|
|
|
|
|
var timers=[] |
|
|
|
|
var timerItems=data.data.filter((item)=>item.obtained!=item.required&&item.timer_start!=null&&item.timer_start.length>0) |
|
|
|
|
for (item of timerItems){ |
|
|
|
|
var splitter=item.timer_start.split(",") |
|
|
|
|
var splitter2=item.timer_end.split(",") |
|
|
|
|
var i=0 |
|
|
|
|
for (var t of splitter){ |
|
|
|
|
var newItem={...item} |
|
|
|
|
newItem.timer_start=t |
|
|
|
|
newItem.timer_end=splitter2[i++] |
|
|
|
|
timers=[...timers,newItem] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
setTimerList(timers) |
|
|
|
|
setData(data.data.slice(dataSplitters[0],dataSplitters[1])) |
|
|
|
|
setData2(data.data.slice(dataSplitters[1],dataSplitters[2])) |
|
|
|
|
setData3(data.data.slice(dataSplitters[2],dataSplitters[3])) |
|
|
|
@ -773,7 +919,7 @@ function App() { |
|
|
|
|
return (
|
|
|
|
|
<Container className="bg-dark" fluid> |
|
|
|
|
<Navbar bg="dark" variant="dark"> |
|
|
|
|
<Container> |
|
|
|
|
<Container fluid> |
|
|
|
|
<Navbar.Brand href="#home"> |
|
|
|
|
<img src={process.env.PUBLIC_URL+"/favicon.ico"} width="30" height="30" className="d-inline-block align-top" alt="BUN logo"/> BUN Collab App |
|
|
|
|
</Navbar.Brand> |
|
|
|
@ -784,52 +930,64 @@ function App() { |
|
|
|
|
</>} |
|
|
|
|
</Container> |
|
|
|
|
</Navbar> |
|
|
|
|
<Container> |
|
|
|
|
{contributor.length===0?<> |
|
|
|
|
<input placeHolder="e.g. Bun" onKeyDown={(k)=>{if (k.key==='Enter') {setContributor(document.getElementById("username").value)}}} id="username"/> |
|
|
|
|
<button type="Submit" onClick={(f)=>{setContributor(document.getElementById("username").value)}}>Submit</button> |
|
|
|
|
</>: |
|
|
|
|
nav==="main"? |
|
|
|
|
data.length>0? |
|
|
|
|
<> |
|
|
|
|
<Row><Col className="text-white"> |
|
|
|
|
<span style={{fontSize:"2em",paddingRight:"10px"}}>{Math.floor(Number(completeRatio)+Number(inProgressRatio)+Number(craftsRatio))}% complete</span><sub>({itemCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " / " + totalItemCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")})</sub> |
|
|
|
|
</Col></Row> |
|
|
|
|
<Row> |
|
|
|
|
<ProgressBar className="bg-dark text-white"> |
|
|
|
|
<ProgressBar animated striped variant="success" label={`${completeRatio}%`} now={completeRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="info" label={`${inProgressRatio}%`} now={inProgressRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="danger" label={`${craftsRatio}%`} now={craftsRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="dark" now={missingProgressRatio} /> |
|
|
|
|
</ProgressBar> |
|
|
|
|
</Row> |
|
|
|
|
<Row> |
|
|
|
|
<Form> |
|
|
|
|
<Form.Group className="mb-3"> |
|
|
|
|
<Form.Control id="searchBar" className="bg-dark text-white" type="text" placeholder="Search Item" onChange={(f)=>{ |
|
|
|
|
updateSearch(f.currentTarget.value) |
|
|
|
|
}} /> |
|
|
|
|
{matchedItems.map((item)=><Item key={item.obj.id} item={item.obj} setLockout={setLockout} lockout={lockout} contributor={contributor} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}></Item>)} |
|
|
|
|
</Form.Group> |
|
|
|
|
</Form> |
|
|
|
|
</Row> |
|
|
|
|
<Accordion className="bg-dark" defaultActiveKey="0"> |
|
|
|
|
<ItemGroup name="Gathering Items" contributor={contributor} akey="0" data={data} lastModified={lastModified} setLastModified={setLastModified} setData={setData} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory} lockout={lockout} setLockout={setLockout}/> |
|
|
|
|
<ItemGroup name="Other Items" contributor={contributor} akey="1" data={data2} lastModified={lastModified} setLastModified={setLastModified} setData={setData2} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory} lockout={lockout} setLockout={setLockout}/> |
|
|
|
|
<ItemGroup name="Pre-crafting" contributor={contributor} akey="2" data={data3} lastModified={lastModified} setLastModified={setLastModified} setData={setData3} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory} lockout={lockout} setLockout={setLockout}/> |
|
|
|
|
<ItemGroup name="Crafting Items" contributor={contributor} akey="3" data={data4} lastModified={lastModified} setLastModified={setLastModified} setData={setData4} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory} lockout={lockout} setLockout={setLockout}/> |
|
|
|
|
</Accordion> |
|
|
|
|
</>:<Importer></Importer> |
|
|
|
|
:nav==="list"?<ListApp transferItems={transferItems}></ListApp>: |
|
|
|
|
<></> |
|
|
|
|
} |
|
|
|
|
<div style={{pointerEvents:"none",position:"fixed",top:"0px",left:"0px",width:"100%",height:"100%"}}> |
|
|
|
|
<ToastContainer position="bottom-end"> |
|
|
|
|
{notifications.map((not)=>{ |
|
|
|
|
return <Notification key={not.id} not={not}/> |
|
|
|
|
})} |
|
|
|
|
</ToastContainer> |
|
|
|
|
</div> |
|
|
|
|
<Container fluid> |
|
|
|
|
<Row> |
|
|
|
|
<Col sm={1}></Col> |
|
|
|
|
<Col sm={8}> |
|
|
|
|
{contributor.length===0?<> |
|
|
|
|
<input placeHolder="e.g. Bun" onKeyDown={(k)=>{if (k.key==='Enter') {setContributor(document.getElementById("username").value)}}} id="username"/> |
|
|
|
|
<button type="Submit" onClick={(f)=>{setContributor(document.getElementById("username").value)}}>Submit</button> |
|
|
|
|
</>: |
|
|
|
|
nav==="main"? |
|
|
|
|
data.length>0? |
|
|
|
|
<> |
|
|
|
|
<Row><Col className="text-white"> |
|
|
|
|
<span style={{fontSize:"2em",paddingRight:"10px"}}>{Math.floor(Number(completeRatio)+Number(inProgressRatio)+Number(craftsRatio))}% complete</span><sub>({itemCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " / " + totalItemCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")})</sub> |
|
|
|
|
</Col></Row> |
|
|
|
|
<Row> |
|
|
|
|
<ProgressBar className="bg-dark text-white"> |
|
|
|
|
<ProgressBar animated striped variant="success" label={`${completeRatio}%`} now={completeRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="info" label={`${inProgressRatio}%`} now={inProgressRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="danger" label={`${craftsRatio}%`} now={craftsRatio} /> |
|
|
|
|
<ProgressBar animated striped variant="dark" now={missingProgressRatio} /> |
|
|
|
|
</ProgressBar> |
|
|
|
|
</Row> |
|
|
|
|
<Row> |
|
|
|
|
<Form> |
|
|
|
|
<Form.Group className="mb-3"> |
|
|
|
|
<Form.Control id="searchBar" className="bg-dark text-white" type="text" placeholder="Search Item" onChange={(f)=>{ |
|
|
|
|
updateSearch(f.currentTarget.value) |
|
|
|
|
}} /> |
|
|
|
|
{matchedItems.map((item)=><Item key={item.obj.id} item={item.obj} contributor={contributor} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}></Item>)} |
|
|
|
|
</Form.Group> |
|
|
|
|
</Form> |
|
|
|
|
</Row> |
|
|
|
|
<Accordion className="bg-dark" defaultActiveKey="0"> |
|
|
|
|
<ItemGroup name="Gathering Items" contributor={contributor} akey="0" data={data} lastModified={lastModified} setLastModified={setLastModified} setData={setData} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}/> |
|
|
|
|
<ItemGroup name="Other Items" contributor={contributor} akey="1" data={data2} lastModified={lastModified} setLastModified={setLastModified} setData={setData2} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}/> |
|
|
|
|
<ItemGroup name="Pre-crafting" contributor={contributor} akey="2" data={data3} lastModified={lastModified} setLastModified={setLastModified} setData={setData3} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}/> |
|
|
|
|
<ItemGroup name="Crafting Items" contributor={contributor} akey="3" data={data4} lastModified={lastModified} setLastModified={setLastModified} setData={setData4} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4} itemCount={itemCount} totalItemCount={totalItemCount} playerInventory={playerInventory}/> |
|
|
|
|
</Accordion> |
|
|
|
|
</>:<Importer></Importer> |
|
|
|
|
:nav==="list"?<ListApp transferItems={transferItems}></ListApp>: |
|
|
|
|
<></> |
|
|
|
|
} |
|
|
|
|
<div style={{pointerEvents:"none",position:"fixed",top:"0px",left:"0px",width:"100%",height:"100%"}}> |
|
|
|
|
<ToastContainer position="bottom-end"> |
|
|
|
|
{notifications.map((not)=>{ |
|
|
|
|
return <Notification key={not.id} not={not}/> |
|
|
|
|
})} |
|
|
|
|
</ToastContainer> |
|
|
|
|
</div> |
|
|
|
|
</Col> |
|
|
|
|
{contributor.length>0&& |
|
|
|
|
<Col sm={3} className="text-white"> |
|
|
|
|
<span style={{fontSize:24,marginRight:"24px"}}>Timers</span><i>ET: {eorzeanTime}</i> |
|
|
|
|
{timerCutList1.map((timer,i)=><TimerDisplay timer={timer} key={i} eorzeanTime={eorzeanTime}/>)} |
|
|
|
|
{timerCutList2.map((timer,i)=><TimerDisplay timer={timer} key={i} eorzeanTime={eorzeanTime}/>)} |
|
|
|
|
</Col> |
|
|
|
|
} |
|
|
|
|
</Row> |
|
|
|
|
</Container> |
|
|
|
|
</Container> |
|
|
|
|
); |
|
|
|
|