Skip to content

Commit

Permalink
Merge pull request #140 from hotosm/feat/drone-operator-task-page
Browse files Browse the repository at this point in the history
Feat/drone-operator-task-page
  • Loading branch information
varun2948 authored Aug 12, 2024
2 parents d34d6d5 + 212b622 commit 7f17bc3
Show file tree
Hide file tree
Showing 16 changed files with 542 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { v4 as uuidv4 } from 'uuid';

interface IDescriptionBoxComponentProps {
title: string;
data: {
name: string;
value: string;
}[];
}
const DescriptionBoxComponent = ({
title,
data,
}: IDescriptionBoxComponentProps) => {
return (
<>
<div className="naxatw-flex naxatw-flex-col naxatw-gap-3">
<p className="naxatw-text-[0.875rem] naxatw-font-semibold naxatw-leading-normal naxatw-tracking-[0.0175rem] naxatw-text-[#D73F3F]">
{title}
</p>
<div className="naxatw-flex naxatw-flex-col naxatw-gap-2">
{data?.map(item => (
<div
className="naxatw-flex naxatw-w-full naxatw-gap-2"
key={uuidv4()}
>
<p className="naxatw-w-[6.875rem] naxatw-text-[0.75rem] naxatw-text-[#484848]">
{item.name}
</p>
<p className="naxatw-text-[0.75rem] naxatw-text-[#484848]">:</p>
<p className="naxatw-text-[0.75rem] naxatw-text-[#484848]">
{item.value}
</p>
</div>
))}
</div>
</div>
</>
);
};

export default DescriptionBoxComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { v4 as uuidv4 } from 'uuid';

import { useTypedSelector } from '@Store/hooks';

import { descriptionData, descriptionTitle } from '@Constants/droneOperator';
import DescriptionBoxComponent from './DescriptionComponent';
import QuestionBox from '../QuestionBox';

const DescriptionBox = () => {
const secondPageStates = useTypedSelector(state => state.droneOperatorTask);
const { secondPage } = secondPageStates;

return (
<>
{/* --------------Generates Description Boxes --------------------- */}
<div className="naxatw-flex naxatw-flex-col naxatw-gap-5">
{descriptionData.map((details, index) => (
<DescriptionBoxComponent
title={descriptionTitle[index]}
data={details}
key={uuidv4()}
/>
))}
</div>
{!secondPage && <QuestionBox />}
</>
);
};

export default DescriptionBox;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
interface IFilesUploadingPopOverProps {
show: boolean;
}

const FilesUploadingPopOver = ({ show }: IFilesUploadingPopOverProps) => {
return (
<>
<div
className={`naxatw-absolute naxatw-left-1/2 naxatw-top-1/2 naxatw-h-[25rem] naxatw-w-1/2 naxatw-translate-x-[-50%] naxatw-translate-y-[-50%] naxatw-bg-white ${show ? 'naxatw-block' : 'naxatw-hidden'} naxatw-rounded-xl naxatw-border naxatw-border-gray-200 naxatw-px-5 naxatw-py-3 naxatw-shadow-sm`}
>
<h1 className="naxatw-text-center naxatw-text-base">Files Uploading</h1>
<div className="naxatw-h-[4rem] naxatw-w-full naxatw-bg-gray-300">
<div
className="naxatw-h-[4rem] naxatw-bg-[#D73F3F]"
style={{ width: '50%' }}
/>
</div>
<h5 className="naxatw-mt-5 naxatw-text-center">
4 / 12 Files Uploaded
</h5>
</div>
</>
);
};

export default FilesUploadingPopOver;
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* eslint-disable no-console */
import { useState } from 'react';
import { motion } from 'framer-motion';
import { Button } from '@Components/RadixComponents/Button';
import { setSecondPage } from '@Store/actions/droneOperatorTask';
import { useTypedDispatch } from '@Store/hooks';
import { postUnflyableComment } from '@Services/droneOperator';
import { useMutation } from '@tanstack/react-query';

const QuestionBox = () => {
const dispatch = useTypedDispatch();
const [flyable, setFlyable] = useState('yes');
const [comment, setComment] = useState('');
const variants = {
open: { opacity: 1, y: 0 },
closed: { opacity: 0, y: '-100%' },
};
function handleFlyableChange(e: React.ChangeEvent<HTMLInputElement>) {
setFlyable(e.target.value);
}

const projectId = '9deb9a04-374a-40ab-ae81-3d44812b27ec';
const taskId = 'f2c7fde5-33d3-4a84-aa34-413a62409df2';
const mutation = useMutation(
(data: any) => postUnflyableComment({ projectId, taskId, data }),
{
onSuccess: () => {
// Optionally, refetch queries or show a success message
console.log('User created successfully');
},
onError: error => {
// Handle error
console.error('Error creating user:', error);
},
},
);
function handleSubmit() {
if (flyable === 'no') {
const data = {
event: 'comment',
newComment: comment,
};
mutation.mutate(data);
} else {
dispatch(setSecondPage(true));
}
}

return (
<>
<div className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-gap-5">
<div className="naxatw-flex naxatw-flex-col naxatw-gap-2">
<p className="naxatw-text-[0.875rem] naxatw-font-semibold naxatw-leading-normal naxatw-text-[#212121]">
Is this task flyable ?
</p>
<div className="naxatw-flex naxatw-flex-col">
<div className="naxatw-flex naxatw-items-center naxatw-gap-1">
<input
type="radio"
id="yes"
value="yes"
checked={flyable === 'yes'}
onChange={handleFlyableChange}
/>
<label
htmlFor="yes"
className="naxatw-text-[0.875rem] naxatw-text-[#212121]"
>
Yes
</label>
</div>
<div className="naxatw-flex naxatw-items-center naxatw-gap-1">
<input
type="radio"
id="no"
value="no"
checked={flyable === 'no'}
onChange={handleFlyableChange}
/>
<label
htmlFor="no"
className="naxatw-text-[0.875rem] naxatw-text-[#212121]"
>
No
</label>
</div>
</div>
</div>
<motion.div
animate={flyable === 'yes' ? 'closed' : 'open'}
variants={variants}
className={` ${flyable === 'yes' ? 'naxatw-hidden' : 'naxatw-block'} naxatw-flex naxatw-flex-col naxatw-items-start naxatw-gap-1 naxatw-self-stretch`}
>
<p className="naxatw-text-[0.875rem] naxatw-font-semibold naxatw-text-[#484848]">
Comment
</p>
<textarea
className="naxatw-w-full naxatw-resize-none naxatw-rounded-[0.25rem] naxatw-border naxatw-border-[#555] naxatw-p-2"
placeholder="Comment"
value={comment}
onChange={e => setComment(e.target.value)}
/>
</motion.div>
<Button
variant="ghost"
rightIcon={flyable === 'yes' ? 'chevron_right' : ''}
className="naxatw-w-fit naxatw-bg-[#D73F3F] naxatw-text-[#FFFFFF]"
onClick={() => handleSubmit()}
disabled={flyable === 'no' && comment.length < 6}
isLoading={mutation.isLoading}
>
{flyable === 'no' ? 'Save' : 'Proceed'}
</Button>
</div>
</>
);
};
export default QuestionBox;
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// import { useState } from 'react';
// import FileUpload from '@Components/common/UploadArea';
// import { Button } from '@Components/RadixComponents/Button';
// import Popover from '@Components/RadixComponents/Popover';
// import FilesUploadingPopOver from '../PopoverBox';

const UploadsBox = () => {
// const [files, setFiles] = useState([]);
// const [popoverOpen, setPopoverOpen] = useState(false);

// const handleFileChange = (event: any) => {
// const selectedFiles = event.target.files;
// // Convert FileList to an array
// const filesArray = Array.from(selectedFiles);
// setFiles(filesArray);
// };
return (
<>
<div className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-gap-5">
<div className="naxatw-flex naxatw-flex-col naxatw-gap-3">
<p className="naxatw-text-[0.875rem] naxatw-font-semibold naxatw-leading-normal naxatw-tracking-[0.0175rem] naxatw-text-[#D73F3F]">
Upload Raw Image
</p>
{/* <FileUpload
name="outline_geojson"
data={[]}
// onChange={handleProjectAreaFileChange}
fileAccept=".jpg, ."
placeholder="*The supported file formats are jpeg,pn"
// isValid={validateAreaOfFileUpload}
// {...formProps}
webkitdirectory=""
directory=""
multiple
control={() => {}}
register={() => {}}
/> */}
</div>
{/* <input
type="file"
// @ts-ignore
webkitDirectory=""
directory=""
multiple
onChange={handleFileChange}
/>
<Button
variant="ghost"
className="naxatw-mx-auto naxatw-w-fit naxatw-bg-[#D73F3F] naxatw-text-[#FFFFFF]"
onClick={() => setPopoverOpen(true)}
>
Save
</Button>
<FilesUploadingPopOver show={popoverOpen} /> */}
</div>
</>
);
};
export default UploadsBox;
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* eslint-disable no-nested-ternary */
import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';

import { Button } from '@Components/RadixComponents/Button';
import Tab from '@Components/common/Tabs';
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import { setSecondPageState } from '@Store/actions/droneOperatorTask';

import UploadsBox from './UploadsBox';
import DescriptionBox from './DescriptionBox';

const DroneOperatorDescriptionBox = () => {
const secondPageStates = useTypedSelector(state => state.droneOperatorTask);
const { secondPageState, secondPage } = secondPageStates;
const [animated, setAnimated] = useState(false);
useEffect(() => {
setAnimated(true);
setTimeout(() => {
setAnimated(false);
}, 100);
}, [secondPageState, secondPage]);
const variants = {
open: { opacity: 1, y: 0 },
closed: { opacity: 0, y: '50%' },
};
const renderComponent = (role: string) => {
switch (role) {
case 'description':
return (
<motion.div
animate={animated ? 'closed' : 'open'}
variants={{ ...variants }}
className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-items-start naxatw-gap-5"
>
<DescriptionBox />
</motion.div>
);
case 'uploads':
return (
<motion.div
animate={animated ? 'closed' : 'open'}
variants={{ ...variants }}
className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-items-start naxatw-gap-5"
>
<UploadsBox />
</motion.div>
);
default:
return (
<motion.div
animate={animated ? 'closed' : 'open'}
variants={{ ...variants }}
className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-items-start naxatw-gap-5"
>
<DescriptionBox />
</motion.div>
);
}
};
const dispatch = useTypedDispatch();

const headerTabOptions = [
{
id: 1,
label: 'Description',
value: 'description',
},
{
id: 2,
label: 'Uploads',
value: 'uploads',
},
];

return (
<>
<div className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-items-start naxatw-gap-5">
<div className="naxatw-flex naxatw-w-full naxatw-items-center naxatw-justify-between naxatw-self-stretch">
<p className="naxatw-text-[0.875rem] naxatw-font-normal naxatw-leading-normal naxatw-text-[#484848]">
Task #74936
</p>
<Button
variant="ghost"
className="naxatw-border naxatw-border-[#D73F3F] naxatw-text-[0.875rem] naxatw-text-[#D73F3F]"
leftIcon="download"
iconClassname="naxatw-text-[1.125rem]"
>
Download Flight Plan
</Button>
</div>
<Tab
onTabChange={value => {
dispatch(setSecondPageState(value));
}}
tabOptions={headerTabOptions}
activeTab={secondPageState}
orientation="row"
className={`naxatw-h-[3rem] naxatw-border-b naxatw-bg-transparent hover:naxatw-border-b-2 hover:naxatw-border-red ${!secondPage ? 'naxatw-hidden' : 'naxatw-block'}`}
activeClassName="naxatw-border-b-2 naxatw-bg-transparent naxatw-border-red"
clickable
/>
{renderComponent(secondPageState)}
</div>
</>
);
};

export default DroneOperatorDescriptionBox;
Loading

0 comments on commit 7f17bc3

Please sign in to comment.