diff --git a/src/app/dashboard/components/Dashboard.jsx b/src/app/dashboard/components/Dashboard.jsx
index 4e89dc6..7160a24 100644
--- a/src/app/dashboard/components/Dashboard.jsx
+++ b/src/app/dashboard/components/Dashboard.jsx
@@ -1,13 +1,11 @@
'use client'
-// import Overview from '../overview/components/Overview'
import SidebarDashboard from './sidebar/Sidebar'
function Dashboard () {
return (
- {/* */}
)
}
diff --git a/src/app/dashboard/components/sidebar/FilterDatePicker.jsx b/src/app/dashboard/components/sidebar/FilterDatePicker.jsx
new file mode 100644
index 0000000..60d2911
--- /dev/null
+++ b/src/app/dashboard/components/sidebar/FilterDatePicker.jsx
@@ -0,0 +1,24 @@
+import Datepicker from 'react-tailwindcss-datepicker'
+import { useState } from 'react'
+
+const FilterDatepicker = () => {
+ const [value, setValue] = useState()
+ const handleChange = (value) => {
+ setValue(value)
+ console.log('Filtering contracts by: date range - ', value)
+ }
+
+ return (
+
+ )
+}
+
+export default FilterDatepicker
diff --git a/src/app/dashboard/components/sidebar/Sidebar.jsx b/src/app/dashboard/components/sidebar/Sidebar.jsx
index fa00356..4ee7d4c 100644
--- a/src/app/dashboard/components/sidebar/Sidebar.jsx
+++ b/src/app/dashboard/components/sidebar/Sidebar.jsx
@@ -1,12 +1,34 @@
-import { Sidebar } from 'flowbite-react'
-import { useRouter } from 'next/navigation'
+import { Checkbox, Label, ListGroup, Sidebar } from 'flowbite-react'
+import { HiSwitchVertical, HiFilter, HiChartPie, HiShoppingBag } from 'react-icons/hi'
+import { usePathname, useRouter } from 'next/navigation'
import customTheme from './style'
+import FilterDatepicker from './FilterDatePicker'
+import { useEffect, useState } from 'react'
function SidebarDashboard () {
- const router = useRouter();
+ const router = useRouter()
+ const pathname = usePathname()
+ const [isContracts, setContracts] = useState(false)
+ const [selectedCategory, setSelectedCategory] = useState(null)
const handleItemClick = (path) => {
- router.push(`/dashboard/${path}`);
+ if (path === 'contracts') {
+ setContracts(true)
+ }
+ router.push(`/dashboard/${path}`)
}
+
+ const handleCheckbox = (category) => {
+ setSelectedCategory(category === selectedCategory ? null : category)
+ console.log('Filtering contracts by:', category)
+ }
+ useEffect(() => {
+ if (pathname === '/dashboard/contracts') {
+ setContracts(true)
+ }
+ }, [pathname])
+
+ const sort = ['Creation date', 'Name', 'Price']
+
return (
@@ -14,22 +36,44 @@ function SidebarDashboard () {
handleItemClick('overview')}>
handleItemClick('contracts')} labelColor='dark'>
+ {isContracts &&
+
+
+
+
+ {sort.map((category, index) => (
+
+ handleCheckbox(category)}
+ />
+
+
+ ))}
+
+
+
+
+ Creation date
+
+
+ }
diff --git a/src/app/dashboard/components/sidebar/style.tsx b/src/app/dashboard/components/sidebar/style.tsx
index adb58bc..40bfff4 100644
--- a/src/app/dashboard/components/sidebar/style.tsx
+++ b/src/app/dashboard/components/sidebar/style.tsx
@@ -1,4 +1,5 @@
import { FlowbiteSidebarTheme } from 'flowbite-react'
+
const customTheme: FlowbiteSidebarTheme = {
"root": {
"base": "h-full",
diff --git a/src/app/dashboard/contracts/components/ButtonGroup.jsx b/src/app/dashboard/contracts/components/ButtonGroup.jsx
new file mode 100644
index 0000000..91f67d8
--- /dev/null
+++ b/src/app/dashboard/contracts/components/ButtonGroup.jsx
@@ -0,0 +1,23 @@
+import { HiDownload, HiUpload } from 'react-icons/hi'
+import { Button } from 'flowbite-react'
+
+function ButtonGroup () {
+ return (
+
+
+
+
+ )
+}
+
+export default ButtonGroup
diff --git a/src/app/dashboard/contracts/components/ContractItem.jsx b/src/app/dashboard/contracts/components/ContractItem.jsx
new file mode 100644
index 0000000..0028543
--- /dev/null
+++ b/src/app/dashboard/contracts/components/ContractItem.jsx
@@ -0,0 +1,86 @@
+import Image from 'next/image'
+import { Accordion, Table } from 'flowbite-react'
+import { HiOutlineCurrencyEuro, HiCalendar, HiDotsHorizontal, HiCheck, HiExclamationCircle } from 'react-icons/hi'
+import mockContractTransfer from '@/utils/data/mockContractTransfers.json'
+
+function ContractItem ({ vc, price }) {
+ const maxLengthTitle = 42
+ const maxLengthDescription = 60
+ const name = vc.title.length > maxLengthTitle ? vc.title.substring(0, maxLengthTitle) + '...' : vc.title
+ const description = vc.short_description.length > maxLengthDescription ? vc.short_description.substring(0, maxLengthDescription) + '...' : vc.short_description
+ const issuanceDate = vc.created_at ? new Date(vc.created_at) : new Date()
+ const date = isNaN(issuanceDate.getTime()) ? new Date() : issuanceDate
+ const provider = vc.provider
+ const providedBy = provider.name ?? 'OTHER'
+ const validatedPrice = price ?? '0'
+ const history = mockContractTransfer.transfer_history
+ const historyData = ['', 'Status', 'Date', 'Transfer ID']
+
+ return (
+
+
+
+
+
+
{name}
+
+
{description}
+ {/* Price and date */}
+
+
+
+
{date.toISOString().split('T')[0]}
+
+
+
+
{validatedPrice} euros
+
+
+
+
+
+
+
+
+
+
+
+ {historyData.map((nameColumn, index) => {
+ return ({nameColumn})
+ })}
+
+
+ {history.map((asset, index) => {
+ return (
+
+ {asset.status === 'Completed' &&
+
+
+ }
+ {asset.status === 'In progress' &&
+
+
+ }
+ {asset.status === 'Failed' &&
+
+
+ }
+ {asset.status}
+ {asset.date}
+ {asset.transfer_id}
+
+ )
+ })}
+
+
+
+
+
+
+ )
+}
+
+export default ContractItem
diff --git a/src/app/dashboard/contracts/components/Contracts.jsx b/src/app/dashboard/contracts/components/Contracts.jsx
new file mode 100644
index 0000000..02680cd
--- /dev/null
+++ b/src/app/dashboard/contracts/components/Contracts.jsx
@@ -0,0 +1,76 @@
+'use client'
+
+import { Pagination } from 'flowbite-react'
+import { useState, useMemo, useEffect, useRef } from 'react'
+import Link from 'next/link'
+import { HiSearch } from 'react-icons/hi'
+import { calculateTotalPages } from '@/app/catalogue/utils/paginationHelpers'
+import SidebarDashboard from '../../components/sidebar/Sidebar'
+import ButtonGroup from './ButtonGroup'
+import ContractItem from './ContractItem'
+
+function calculateItemsPerPage (currentPage, size, data, setContracts) {
+ const startIndex = (currentPage - 1) * size
+ const endIndex = (currentPage * size) > data.total ? data.total : currentPage * size
+ setContracts(data.slice(startIndex, endIndex))
+}
+function Contracts ({ data }) {
+ const [currentPage, setCurrentPage] = useState(1)
+ const [contracts, setContracts] = useState([])
+ const ref = useRef(null)
+
+ useEffect(() => {
+ if (data) {
+ setContracts(data)
+ }
+ }, [data])
+
+ useEffect(() => {
+ window.scrollTo(0, 0, 'smooth')
+ calculateItemsPerPage(currentPage, 2, data, setContracts)
+ }, [currentPage, data])
+
+ const handleSearch = (e) => {
+ console.log('Searching contracts by: ', e.target.value)
+ ref.current.value = ''
+ }
+ const totalPages = useMemo(() => calculateTotalPages(data.length, 2), [data.length])
+ const totalPagesToDisplay = totalPages
+ const onPageChange = (page) => setCurrentPage(page)
+ return (
+
+
+
+
+
+
+
+ {
+ if (e.key === 'Enter') {
+ handleSearch(e)
+ }
+ }}
+ />
+
+
+
+ {contracts.map((contract, index) => {
+ return (
+
+
+
+ )
+ })}
+
+
+ )
+}
+export default Contracts
diff --git a/src/app/dashboard/contracts/page.js b/src/app/dashboard/contracts/page.js
new file mode 100644
index 0000000..e81ff87
--- /dev/null
+++ b/src/app/dashboard/contracts/page.js
@@ -0,0 +1,11 @@
+import Contracts from './components/Contracts'
+import mockContract from '@/utils/data/mockContract.json'
+
+export default function Page () {
+ const contracts = mockContract
+ return (
+
+
+
+ )
+}
diff --git a/src/app/dashboard/overview/components/Overview.jsx b/src/app/dashboard/overview/components/Overview.jsx
index c286e23..e73c894 100644
--- a/src/app/dashboard/overview/components/Overview.jsx
+++ b/src/app/dashboard/overview/components/Overview.jsx
@@ -9,10 +9,10 @@ function Overview () {
return (
)
}
diff --git a/src/app/dashboard/overview/components/TransferHistory.jsx b/src/app/dashboard/overview/components/TransferHistory.jsx
index d16346f..41dbd56 100644
--- a/src/app/dashboard/overview/components/TransferHistory.jsx
+++ b/src/app/dashboard/overview/components/TransferHistory.jsx
@@ -1,4 +1,5 @@
import { Table, Accordion } from 'flowbite-react'
+import { HiDownload, HiUpload, HiDotsHorizontal, HiExclamationCircle } from 'react-icons/hi'
function TransferHistory ({ history }) {
const historyData = ['', 'Asset', 'Counterparty ID', 'Status', 'Date']
@@ -27,28 +28,19 @@ function TransferHistory ({ history }) {
{asset.transfer_in &&
-
+
}
{asset.transfer_out &&
-
+
}
{!asset.transfer_out && !asset.transfer_in && asset.status === 'Pending' &&
-
+
}
{!asset.transfer_out && !asset.transfer_in && asset.status === 'Failed' &&
-
+
}
{asset.asset}
diff --git a/src/components/nav/NavItems.jsx b/src/components/nav/NavItems.jsx
index 862a2d9..ba3728a 100644
--- a/src/components/nav/NavItems.jsx
+++ b/src/components/nav/NavItems.jsx
@@ -7,7 +7,7 @@ export const NavItems = () => {
// THESE TWO SHOULD BE PROTECTED, ONLY ACCESSED BY REGISTERED USERS
// @TODO: Implement Metamask plugin + a session provider to show only if logged in.
{ href: '/publish', label: 'Publish' },
- { href: '/dashboard', label: 'Dashboard' }
+ { href: '/dashboard/overview', label: 'Dashboard' }
]
return (
diff --git a/src/utils/data/mockContract.json b/src/utils/data/mockContract.json
new file mode 100644
index 0000000..278b61e
--- /dev/null
+++ b/src/utils/data/mockContract.json
@@ -0,0 +1,138 @@
+[
+ {
+ "title": "Breast cancer data (2022 update)",
+ "id": "did:web:example.com:dataset:climate-change-analysis-2022",
+ "short_description": "Breast cancer labelled data from 2020 to 2022 in France",
+ "provider": {
+ "name": "Care & Co SARL ",
+ "id": "did:web:example.com:provider:climate-change-analysis-2022",
+ "email": "example@noaa.com",
+ "url": "https://oceanservice.noaa.gov/",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 50,
+ "picture": "/img/mock_asset_img.jpg",
+ "created_at": "2023-12-03T10:24:00",
+ "updated_at": "2023-10-05T14:30:00",
+ "keywords": [
+ "cancer",
+ "health "
+ ],
+ "location": "London, UK",
+ "description": "This dataset provides comprehensive data on various climate metrics for the year 2022. It includes detailed information on temperature changes, precipitation patterns, and carbon emissions. The data is sourced from the National Oceanic and Atmospheric Administration (NOAA) and is designed to support research and policy-making efforts related to climate change. Users can analyze trends over time and compare data across different regions to gain insights into the impacts of climate change."
+ },
+ {
+ "title": "Eviden HPC",
+ "id": "did:web:example.com:dataset:climate-change-analysis-2022",
+ "short_description": "Eviden HPC service to execute expensive computing tasks quickly and easily",
+ "provider": {
+ "name": "Bruxelloise des logiciels SRL",
+ "id": "did:web:example.com:provider:climate-change-analysis-2022",
+ "email": "example@noaa.com",
+ "url": "https://oceanservice.noaa.gov/",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 6,
+ "picture": "/img/mock_asset_img.jpg",
+ "created_at": "2023-11-09T10:24:00",
+ "updated_at": "2023-10-05T14:30:00",
+ "keywords": [
+ "cancer",
+ "health "
+ ],
+ "location": "London, UK",
+ "description": "This dataset provides comprehensive data on various climate metrics for the year 2022. It includes detailed information on temperature changes, precipitation patterns, and carbon emissions. The data is sourced from the National Oceanic and Atmospheric Administration (NOAA) and is designed to support research and policy-making efforts related to climate change. Users can analyze trends over time and compare data across different regions to gain insights into the impacts of climate change."
+ },
+ {
+ "title": "Renewable Energy Trends",
+ "id": "did:web:example.com:dataset:renewable-energy-2023",
+ "short_description": "A dataset covering global renewable energy trends and statistics.",
+ "provider": {
+ "name": "Green Energy Analytics",
+ "id": "did:web:example.com:provider:renewable-energy",
+ "email": "contact@gea.com",
+ "url": "https://renewableanalytics.com",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 25,
+ "picture": "/img/energy_asset_img.jpg",
+ "created_at": "2024-01-15T10:24:00",
+ "updated_at": "2024-02-05T14:30:00",
+ "keywords": [
+ "renewable",
+ "energy",
+ "sustainability"
+ ],
+ "location": "Berlin, Germany",
+ "description": "Explore global renewable energy adoption trends, including solar, wind, and hydroelectric power data from 2023."
+ },
+ {
+ "title": "Urban Mobility Insights",
+ "id": "did:web:example.com:dataset:urban-mobility",
+ "short_description": "Urban mobility statistics and insights from 2022.",
+ "provider": {
+ "name": "City Move Analytics",
+ "id": "did:web:example.com:provider:urban-mobility",
+ "email": "support@citymove.com",
+ "url": "https://citymoveanalytics.com",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 15,
+ "picture": "/img/mobility_asset_img.jpg",
+ "created_at": "2023-10-12T12:24:00",
+ "updated_at": "2023-11-01T14:30:00",
+ "keywords": [
+ "mobility",
+ "transportation",
+ "cities"
+ ],
+ "location": "Amsterdam, Netherlands",
+ "description": "Comprehensive data on urban transportation patterns, including ride-sharing, public transit, and traffic congestion metrics."
+ },
+ {
+ "title": "AI Ethics Dataset",
+ "id": "did:web:example.com:dataset:ai-ethics",
+ "short_description": "AI ethics case studies and policy recommendations.",
+ "provider": {
+ "name": "EthicsAI",
+ "id": "did:web:example.com:provider:ai-ethics",
+ "email": "info@ethicsai.org",
+ "url": "https://ethicsai.org",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 40,
+ "picture": "/img/ai_ethics_img.jpg",
+ "created_at": "2023-05-20T11:24:00",
+ "updated_at": "2023-06-15T16:30:00",
+ "keywords": [
+ "AI",
+ "ethics",
+ "policy"
+ ],
+ "location": "San Francisco, USA",
+ "description": "Case studies and insights on the ethical implications of artificial intelligence in various domains."
+ },
+ {
+ "title": "Wildlife Conservation Metrics",
+ "id": "did:web:example.com:dataset:wildlife-conservation",
+ "short_description": "Wildlife conservation data from 2021 to 2023.",
+ "provider": {
+ "name": "EcoData Foundation",
+ "id": "did:web:example.com:provider:wildlife-conservation",
+ "email": "contact@ecodata.org",
+ "url": "https://ecodata.org",
+ "picture": "https://picsum.photos/200"
+ },
+ "price": 35,
+ "picture": "/img/wildlife_img.jpg",
+ "created_at": "2023-09-05T09:24:00",
+ "updated_at": "2023-12-01T10:30:00",
+ "keywords": [
+ "wildlife",
+ "conservation",
+ "biodiversity"
+ ],
+ "location": "Nairobi, Kenya",
+ "description": "Data covering wildlife conservation efforts, including species population trends and protected area effectiveness."
+ }
+]
diff --git a/src/utils/data/mockContractTransfers.json b/src/utils/data/mockContractTransfers.json
new file mode 100644
index 0000000..c95145b
--- /dev/null
+++ b/src/utils/data/mockContractTransfers.json
@@ -0,0 +1,19 @@
+{
+ "transfer_history": [
+ {
+ "status": "In progress",
+ "date": "Yesterday at 6:31 pm",
+ "transfer_id": "kdjlsfjslf-156416"
+ },
+ {
+ "status": "Completed",
+ "date": "2023-11-29 at 6:31 pm",
+ "transfer_id": "lsjflassfls-519861"
+ },
+ {
+ "status": "Failed",
+ "date": "2023-11-21 at 5:24 am",
+ "transfer_id": "sldfkSƒFLie-56498"
+ }
+ ]
+}
From 93378f28b29721576c3dfdbfe76e04b1313b26c8 Mon Sep 17 00:00:00 2001
From: Nary Lozano
Date: Mon, 25 Nov 2024 11:58:17 +0100
Subject: [PATCH 3/7] Fix formatting sidebar
---
src/app/dashboard/components/sidebar/Sidebar.jsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/app/dashboard/components/sidebar/Sidebar.jsx b/src/app/dashboard/components/sidebar/Sidebar.jsx
index 4ee7d4c..abb41bf 100644
--- a/src/app/dashboard/components/sidebar/Sidebar.jsx
+++ b/src/app/dashboard/components/sidebar/Sidebar.jsx
@@ -1,9 +1,10 @@
+import { useEffect, useState } from 'react'
import { Checkbox, Label, ListGroup, Sidebar } from 'flowbite-react'
import { HiSwitchVertical, HiFilter, HiChartPie, HiShoppingBag } from 'react-icons/hi'
import { usePathname, useRouter } from 'next/navigation'
-import customTheme from './style'
import FilterDatepicker from './FilterDatePicker'
-import { useEffect, useState } from 'react'
+import customTheme from './style'
+
function SidebarDashboard () {
const router = useRouter()
const pathname = usePathname()
From 28de090e71d8d07154d0d095d0b3d961dcfe3ebc Mon Sep 17 00:00:00 2001
From: Nary Lozano
Date: Tue, 17 Dec 2024 15:58:20 +0100
Subject: [PATCH 4/7] Add Sugestions CR 1/2
---
.example.env | 3 ++
next.config.js | 4 +-
.../dashboard/components/sidebar/Sidebar.jsx | 23 ++++++-----
.../dashboard/components/sidebar/style.tsx | 1 +
.../contracts/components/ButtonGroup.jsx | 2 +-
.../contracts/components/ContractItem.jsx | 28 ++++++++-----
.../contracts/components/Contracts.jsx | 41 +++++--------------
.../overview/components/TransferHistory.jsx | 2 +-
src/app/dashboard/page.js | 7 ----
src/utils/settings.js | 1 +
10 files changed, 52 insertions(+), 60 deletions(-)
delete mode 100644 src/app/dashboard/page.js
diff --git a/.example.env b/.example.env
index 016fa99..a83c0bb 100644
--- a/.example.env
+++ b/.example.env
@@ -6,3 +6,6 @@ export LOGOUT_REDIRECT_URL=""
export NEXTAUTH_URL=""
export NEXTAUTH_SECRET=""
export FEDERATED_CATALOGUE_API=""
+export CONTRACTS_PAGE_SIZE=5
+export BATCH_SIZE=40
+
diff --git a/next.config.js b/next.config.js
index 51e93a9..36451cb 100644
--- a/next.config.js
+++ b/next.config.js
@@ -4,6 +4,7 @@ const nextConfig = {
output: 'standalone',
env: {
BATCH_SIZE: process.env.BATCH_SIZE ?? '40',
+ CONTRACTS_PAGE_SIZE: process.env.CONTRACTS_PAGE_SIZE ?? '5',
FEDERATED_CATALOGUE_API: process.env.FEDERATED_CATALOGUE_API
},
async headers () {
@@ -19,7 +20,8 @@ const nextConfig = {
}
]
},
- images: {
+ // TODO: remove when integrating backend component
+ images: {
remotePatterns: [
{
protocol: 'https',
diff --git a/src/app/dashboard/components/sidebar/Sidebar.jsx b/src/app/dashboard/components/sidebar/Sidebar.jsx
index abb41bf..9d545e6 100644
--- a/src/app/dashboard/components/sidebar/Sidebar.jsx
+++ b/src/app/dashboard/components/sidebar/Sidebar.jsx
@@ -1,21 +1,23 @@
import { useEffect, useState } from 'react'
-import { Checkbox, Label, ListGroup, Sidebar } from 'flowbite-react'
+import { Label, ListGroup, Sidebar, Radio } from 'flowbite-react'
import { HiSwitchVertical, HiFilter, HiChartPie, HiShoppingBag } from 'react-icons/hi'
import { usePathname, useRouter } from 'next/navigation'
import FilterDatepicker from './FilterDatePicker'
import customTheme from './style'
function SidebarDashboard () {
+
const router = useRouter()
const pathname = usePathname()
const [isContracts, setContracts] = useState(false)
- const [selectedCategory, setSelectedCategory] = useState(null)
+ const [selectedCategory, setSelectedCategory] = useState( null )
- const handleItemClick = (path) => {
- if (path === 'contracts') {
+ const handleItemClick = (item) => {
+ if (item === 'contracts') {
setContracts(true)
}
- router.push(`/dashboard/${path}`)
+
+ router.push(`/dashboard/${item}`)
}
const handleCheckbox = (category) => {
@@ -35,13 +37,14 @@ function SidebarDashboard () {
- handleItemClick('overview')}>
+ {/* //TODO:first do it, then do it right */}
+ handleItemClick('overview')}className={`${pathname === '/dashboard/overview' ? 'bg-gray-100' : ''}`} >
Overview
- handleItemClick('contracts')} labelColor='dark'>
+ handleItemClick('contracts')} className={`${isContracts ? 'bg-gray-100' : ''}`}>
Contracts
@@ -50,7 +53,7 @@ function SidebarDashboard () {
{isContracts &&
-
+
{sort.map((category, index) => (
@@ -58,7 +61,7 @@ function SidebarDashboard () {
key={`${category}-${index}`}
className='flex items-center border-none focus:ring-0 m-2 ml-4'
>
-
-
+
Creation date
diff --git a/src/app/dashboard/components/sidebar/style.tsx b/src/app/dashboard/components/sidebar/style.tsx
index 40bfff4..63eafe3 100644
--- a/src/app/dashboard/components/sidebar/style.tsx
+++ b/src/app/dashboard/components/sidebar/style.tsx
@@ -1,5 +1,6 @@
import { FlowbiteSidebarTheme } from 'flowbite-react'
+// Custom theme needed to override the root.inner property.
const customTheme: FlowbiteSidebarTheme = {
"root": {
"base": "h-full",
diff --git a/src/app/dashboard/contracts/components/ButtonGroup.jsx b/src/app/dashboard/contracts/components/ButtonGroup.jsx
index 91f67d8..5719b01 100644
--- a/src/app/dashboard/contracts/components/ButtonGroup.jsx
+++ b/src/app/dashboard/contracts/components/ButtonGroup.jsx
@@ -4,7 +4,7 @@ import { Button } from 'flowbite-react'
function ButtonGroup () {
return (
-