From c2015fe8af7f56527095150545932929227b0d4f Mon Sep 17 00:00:00 2001 From: skrushna1506 Date: Fri, 6 Dec 2024 16:39:03 +0530 Subject: [PATCH] feat(open-spark): added changes as per figma for my ders page 1. added add new ders bottom modal ui 2. added delete ders bottom modal ui 3. added get post and delete api logic only --- .../components/deviceList/AddNewDerModal.tsx | 137 +++++++++++++ .../components/deviceList/DeleteDErModal.tsx | 58 ++++++ .../components/deviceList/DeviceList.tsx | 189 ++++++++++++------ apps/open-spark/pages/index.tsx | 70 ++++--- apps/open-spark/pages/myDers.tsx | 46 ++++- apps/open-spark/public/images/PDF.svg | 6 +- 6 files changed, 396 insertions(+), 110 deletions(-) create mode 100644 apps/open-spark/components/deviceList/AddNewDerModal.tsx create mode 100644 apps/open-spark/components/deviceList/DeleteDErModal.tsx diff --git a/apps/open-spark/components/deviceList/AddNewDerModal.tsx b/apps/open-spark/components/deviceList/AddNewDerModal.tsx new file mode 100644 index 00000000..5a8fc70d --- /dev/null +++ b/apps/open-spark/components/deviceList/AddNewDerModal.tsx @@ -0,0 +1,137 @@ +import React, { useState } from 'react' +import BottomModalScan from '@beckn-ui/common/src/components/BottomModal/BottomModalScan' +import { Input, Typography } from '@beckn-ui/molecules' +import BecknButton from '@beckn-ui/molecules/src/components/button' +import { Box, Flex, Image } from '@chakra-ui/react' +import uploadIcon from '@public/images/upload_icon.svg' +import pdfIcon from '@public/images/PDF.svg' +import DragAndDropUpload from '@components/dragAndDropUpload' +import RenderDocuments from '@components/documentsRenderer' + +interface Proofs { + id: number + name: string + date: string +} + +interface DocumentProps { + icon: string + title: string + file: any + date: Date +} + +interface AddNewDerModalProps { + isOpen: boolean + onClose: () => void + proofs: Proofs[] + handleDelete: (id: number) => void + handleFileUpload: (event: any) => void + onSubmit: (category: string, uploadedFiles: File[]) => Promise + isLoading?: boolean +} + +const AddNewDerModal = (props: AddNewDerModalProps) => { + const [category, setCategory] = useState('Lorem Ipsum Dior') + const [uploadedFiles, setUploadedFiles] = useState([]) + const [allFilesProcessed, setAllFilesProcessed] = useState(false) + + const { isOpen, onClose, onSubmit, isLoading } = props + + const handleFileChange = (files: File[]) => { + if (files.length > 0) { + const docs = files.map(file => { + console.log('Selected file:', file) + return { title: file?.name!, icon: pdfIcon, date: new Date(), file: file } + }) + setUploadedFiles(prevState => (prevState ? [...prevState, ...docs] : docs)) + } + } + + const handleAddDevice = () => { + if (!category || uploadedFiles.length === 0) { + alert('Please provide all details.') + return + } + const files = uploadedFiles.map(doc => doc.file) + onSubmit(category, files) + } + const handleOnDelete = (index: number, document: DocumentProps, type: 'cred' | 'upload') => { + if (type === 'cred') { + setUploadedFiles(prevState => prevState!.filter((_, i) => i !== index)) + } + } + + return ( + + + + setCategory(e.target.value)} + /> + + { + setAllFilesProcessed(status) + }} + /> + + { + return ( + { + if (fileInputRef.current) { + fileInputRef.current.click() + } + }} + > + upload + + + + ) + }} + /> + + + + + ) +} + +export default AddNewDerModal diff --git a/apps/open-spark/components/deviceList/DeleteDErModal.tsx b/apps/open-spark/components/deviceList/DeleteDErModal.tsx new file mode 100644 index 00000000..79bf1527 --- /dev/null +++ b/apps/open-spark/components/deviceList/DeleteDErModal.tsx @@ -0,0 +1,58 @@ +import BottomModalScan from '@beckn-ui/common/src/components/BottomModal/BottomModalScan' +import { Typography } from '@beckn-ui/molecules' +import BecknButton from '@beckn-ui/molecules/src/components/button' +import { Box, Flex } from '@chakra-ui/react' +import React from 'react' +interface DeleteDErModalProps { + isOpen: boolean + onClose: () => void + handleConfirmDeleteDevice: () => void + isLoading?: boolean +} + +const DeleteDErModal = (props: DeleteDErModalProps) => { + const { isOpen, onClose, handleConfirmDeleteDevice, isLoading } = props + return ( + + + + + + + + + + + ) +} + +export default DeleteDErModal diff --git a/apps/open-spark/components/deviceList/DeviceList.tsx b/apps/open-spark/components/deviceList/DeviceList.tsx index 1503d14a..8c21652b 100644 --- a/apps/open-spark/components/deviceList/DeviceList.tsx +++ b/apps/open-spark/components/deviceList/DeviceList.tsx @@ -1,11 +1,15 @@ -'use client' - import React, { useState, useEffect } from 'react' import { Box, VStack, IconButton, Container, Flex } from '@chakra-ui/react' import { BiPlusCircle } from 'react-icons/bi' -import { CiCirclePlus, CiCircleMinus } from 'react-icons/ci' -import BecknButton from '@beckn-ui/molecules/src/components/button/Button' +import { CiCircleMinus } from 'react-icons/ci' import { Typography } from '@beckn-ui/molecules' +import AddNewDerModal from './AddNewDerModal' +import DeleteDErModal from './DeleteDErModal' +import axios from 'axios' +import { ROLE, ROUTE_TYPE } from '@lib/config' +import { useSelector } from 'react-redux' +import { RootState } from '@store/index' +import Cookies from 'js-cookie' interface Device { name: string @@ -15,30 +19,109 @@ interface Device { interface DeviceListProps { initialDevices: Device[] initialNearbyDevices: Device[] - onDeviceChange: (devices: Device[], nearbyDevices: Device[]) => void + onDeviceChange: (devices: Device[]) => void + fetchPairedData: () => void } -export default function DeviceList({ initialDevices, initialNearbyDevices, onDeviceChange }: DeviceListProps) { +export default function DeviceList({ initialDevices, onDeviceChange, fetchPairedData }: DeviceListProps) { const [devices, setDevices] = useState(initialDevices) - const [nearbyDevices, setNearbyDevices] = useState(initialNearbyDevices) + const [isModalOpen, setIsModalOpen] = useState(false) + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) + const [selectedDeviceIndex, setSelectedDeviceIndex] = useState(null) + const [isLoading, setIsLoading] = useState(false) + const [isDeleteLoading, setIsDeleteLoading] = useState(false) - useEffect(() => { - onDeviceChange(devices, nearbyDevices) - }, [devices, nearbyDevices, onDeviceChange]) + const strapiUrl = process.env.NEXT_PUBLIC_STRAPI_URL + const { role } = useSelector((state: RootState) => state.auth) + const bearerToken = Cookies.get('authToken') + + const handleAddDevice = async (category: string, uploadedFiles: File[]) => { + setIsLoading(true) + try { + const type = role === ROLE.PRODUCER ? 'PRODUCER' : 'CONSUMER' + const formData = new FormData() + + formData.append('type', type) + formData.append('category', category) + uploadedFiles.forEach(file => formData.append('proofs', file)) + + const response = await axios.post(`${strapiUrl}${ROUTE_TYPE[role!]}/der`, formData, { + headers: { Authorization: `Bearer ${bearerToken}` }, + withCredentials: true + }) - const handleRemoveDevice = (index: number) => { - const newDevices = devices.filter((_, i) => i !== index) - setDevices(newDevices) + if (role === ROLE.PRODUCER) { + setDevices(response.data.production) + setIsLoading(false) + } else if (role === ROLE.CONSUMER) { + setDevices(response.data.consumption) + setIsLoading(false) + } + + fetchPairedData() + setIsModalOpen(false) + } catch (error) { + console.error('Error adding device:', error.message) + } finally { + setIsLoading(false) + handleModalClose() + } } - const handleAddDevice = (index: number) => { - const addedDevice = nearbyDevices[index] - const newNearbyDevices = nearbyDevices.filter((_, i) => i !== index) - const newDevices = [...devices, { ...addedDevice, paired: true }] - setNearbyDevices(newNearbyDevices) - setDevices(newDevices) + const handleModalOpen = () => setIsModalOpen(true) + const handleModalClose = () => setIsModalOpen(false) + + const handleDeleteModalOpen = (index: number) => { + setSelectedDeviceIndex(index) + setIsDeleteModalOpen(true) } + const handleDeleteModalClose = () => { + setSelectedDeviceIndex(null) + setIsDeleteModalOpen(false) + } + + const handleRemoveDevice = async (index: number) => { + setIsDeleteLoading(true) + const deviceToRemove = devices[index] + + try { + const response = await axios.delete(`${strapiUrl}${ROUTE_TYPE[role!]}/der`, { + params: { id: deviceToRemove.id }, + headers: { Authorization: `Bearer ${bearerToken}` }, + withCredentials: true + }) + + if (response.status === 200 || response.status === 204) { + if (role === ROLE.PRODUCER) { + setDevices(response.data.production) + setIsDeleteLoading(false) + } else if (role === ROLE.CONSUMER) { + setDevices(response.data.consumption) + setIsDeleteLoading(false) + } + } else { + console.error('Failed to delete the device:', response.data) + } + } catch (error) { + console.error('Error deleting device:', error.message) + } finally { + // setIsDeleteLoading(false) + handleDeleteModalClose() + } + } + + const handleConfirmDeleteDevice = () => { + if (selectedDeviceIndex !== null) { + handleRemoveDevice(selectedDeviceIndex) + handleDeleteModalClose() + } + } + + useEffect(() => { + onDeviceChange(devices) + }, [devices, onDeviceChange]) + return ( @@ -47,25 +130,26 @@ export default function DeviceList({ initialDevices, initialNearbyDevices, onDev spacing={4} > } variant="ghost" + onClick={handleModalOpen} /> handleRemoveDevice(index)} + onClick={() => handleDeleteModalOpen(index)} style={{ cursor: 'pointer' }} size={24} - opacity={'0.5'} + opacity="0.5" /> ))} - {nearbyDevices.length > 0 ? ( - <> - - - {nearbyDevices.map((device, index) => ( - - - handleAddDevice(index)} - style={{ cursor: 'pointer' }} - size={24} - opacity={0.5} - /> - - ))} - - - ) : null} - - + + + ) } diff --git a/apps/open-spark/pages/index.tsx b/apps/open-spark/pages/index.tsx index 6c920b20..ac7b364b 100644 --- a/apps/open-spark/pages/index.tsx +++ b/apps/open-spark/pages/index.tsx @@ -183,43 +183,47 @@ const Homepage = () => { ))} - - - - - - - - - {currentStatusmockData.map((data, index) => ( - + + + - ))} - - - + + + + + {currentStatusmockData.map((data, index) => ( + + ))} + + + + )} + router.push(role === ROLE.PRODUCER ? '/sellingPreference' : '/buyingPreference')} + sx={{ marginTop: '30px' }} /> { + const strapiUrl = process.env.NEXT_PUBLIC_STRAPI_URL + const { role } = useSelector((state: RootState) => state.auth) + const bearerToken = Cookies.get('authToken') const [devices, setDevices] = useState([ { name: 'Wifi', paired: true }, { name: 'Orient electric Fan', paired: true }, @@ -12,16 +20,36 @@ const MyDers = () => { { name: 'Solar Panel', paired: true } ]) - const [nearbyDevices, setNearbyDevices] = useState([{ name: 'Light', paired: false }]) - - const handleDeviceChange = ( - updatedDevices: React.SetStateAction<{ name: string; paired: boolean }[]>, - updatedNearbyDevices: React.SetStateAction<{ name: string; paired: boolean }[]> - ) => { + const handleDeviceChange = (updatedDevices: React.SetStateAction<{ name: string; paired: boolean }[]>) => { setDevices(updatedDevices) - setNearbyDevices(updatedNearbyDevices) } + const fetchPairedData = async () => { + try { + const response = await axios.get(`${strapiUrl}${ROUTE_TYPE[role!]}/der`, { + headers: { Authorization: `Bearer ${bearerToken}` }, + withCredentials: true + }) + + const result = response.data.data + console.log(result) + + if (role === ROLE.PRODUCER) { + setDevices(result.production) + } else if (role === ROLE.CONSUMER) { + setDevices(result.consumption) + } + } catch (error) { + console.error('Error fetching dashboard data:', error) + } + } + + useEffect(() => { + if (role && bearerToken && strapiUrl) { + fetchPairedData() + } + }, [role, bearerToken, strapiUrl]) + return ( { > ) diff --git a/apps/open-spark/public/images/PDF.svg b/apps/open-spark/public/images/PDF.svg index 04407277..00c01edf 100644 --- a/apps/open-spark/public/images/PDF.svg +++ b/apps/open-spark/public/images/PDF.svg @@ -1,5 +1,5 @@ - - - + + +