Skip to content

Commit

Permalink
eudr - suppliers breakdown foundation
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgnlez committed Mar 5, 2024
1 parent dbcfb87 commit a86b72c
Show file tree
Hide file tree
Showing 29 changed files with 1,234 additions and 181 deletions.
17 changes: 17 additions & 0 deletions client/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/styles/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
10 changes: 9 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
"@json2csv/plainjs": "^6.1.3",
"@loaders.gl/core": "3.3.1",
"@luma.gl/constants": "8.5.18",
"@radix-ui/react-collapsible": "1.0.3",
"@radix-ui/react-label": "2.0.2",
"@radix-ui/react-radio-group": "1.1.3",
"@reduxjs/toolkit": "1.8.2",
"@tailwindcss/forms": "0.4.0",
"@tailwindcss/typography": "0.5.0",
Expand All @@ -43,7 +46,9 @@
"autoprefixer": "10.2.5",
"axios": "1.3.4",
"chroma-js": "2.1.2",
"class-variance-authority": "0.7.0",
"classnames": "2.3.1",
"clsx": "^2.1.0",
"d3-array": "3.0.2",
"d3-format": "3.0.1",
"d3-scale": "4.0.2",
Expand All @@ -52,6 +57,7 @@
"jsona": "1.9.2",
"lodash-es": "4.17.21",
"lottie-react": "2.4.0",
"lucide-react": "0.344.0",
"maplibre-gl": "3.6.2",
"next": "13.5.5",
"next-auth": "4.19.2",
Expand All @@ -70,7 +76,9 @@
"recharts": "2.9.0",
"rooks": "7.14.1",
"sharp": "0.32.6",
"tailwindcss": "3.3.1",
"tailwind-merge": "2.2.1",
"tailwindcss": "3.4.1",
"tailwindcss-animate": "1.0.7",
"uuid": "8.3.2",
"yup": "0.32.11"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const AutoCompleteSelect = <T,>({
{({ open }) => (
<>
{!!label && (
<Combobox.Label className="text-gray-700 block text-sm font-medium">
<Combobox.Label className="block text-sm font-medium text-gray-700">
{label}
</Combobox.Label>
)}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/forms/select/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const Select = <T,>({
{({ open }) => (
<>
{!!label && (
<Listbox.Label className="text-gray-700 block text-sm font-medium">
<Listbox.Label className="block text-sm font-medium text-gray-700">
{label}
</Listbox.Label>
)}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/table/cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const CellWrapper = <T, C>({ children, context }: React.PropsWithChildren<CellPr
onClick={isExpandible ? toggleExpand : undefined}
className={classNames(
getAlignmentClasses(align),
'min-h-20 relative flex w-full items-center justify-start',
'relative flex min-h-20 w-full items-center justify-start',
{
'cursor-pointer': isExpandible,
'ml-7 pr-7': canExpand && !isExpandible && isFirstColumn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Table: React.FC<ButtonProps> = ({
'flex h-10 min-w-[2.5rem] items-center justify-center text-sm',
className,
{
'border-green-700 border-b': active,
'border-b border-green-700': active,
'cursor-pointer': !disabled,
'opacity-30': disabled,
},
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/tabs/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Tabs: React.FC<TabsProps> = ({ activeTab, tabs, bottomBorder = true }: Tab
href={tab.href}
className={classNames('-mb-px py-3', {
'ml-10': index !== 0,
'text-green-700 border-green-700 border-b-2': activeTab && tab === activeTab,
'border-b-2 border-green-700 text-green-700': activeTab && tab === activeTab,
})}
>
{tab.name}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/tree-select/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ const InnerTreeSelect = <IsMulti extends boolean>(
{theme === 'inline-primary' ? (
<div
className={classNames(
'border-t-primary mx-auto mt-0.5 h-0 w-0 border-x-4 border-t-4 border-x-transparent',
'mx-auto mt-0.5 h-0 w-0 border-x-4 border-t-4 border-x-transparent border-t-primary',
{ 'border-t-red-400': error },
)}
/>
Expand Down
9 changes: 9 additions & 0 deletions client/src/components/ui/collapsible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';

const Collapsible = CollapsiblePrimitive.Root;

const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;

const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;

export { Collapsible, CollapsibleTrigger, CollapsibleContent };
19 changes: 19 additions & 0 deletions client/src/components/ui/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cva, type VariantProps } from 'class-variance-authority';

import { cn } from '@/lib/utils';

const labelVariants = cva(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
);

const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
));
Label.displayName = LabelPrimitive.Root.displayName;

export { Label };
36 changes: 36 additions & 0 deletions client/src/components/ui/radio-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
import { Circle } from 'lucide-react';

import { cn } from '@/lib/utils';

const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
return <RadioGroupPrimitive.Root className={cn('grid gap-2', className)} {...props} ref={ref} />;
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;

const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;

export { RadioGroup, RadioGroupItem };
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { formatPercentage } from '@/utils/number-format';

const BreakdownItem = ({
name,
color,
icon,
value,
}: {
name: string;
color: string;
icon: string;
value: number;
}): JSX.Element => {
return (
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="mr-2 h-2 w-2 rounded-full bg-[#4AB7F3]" />
<span>{name}</span>
</div>
<div className="shrink-0 grow-0">
<div className="text-center">
{formatPercentage(value)} <span className="text-xs">of suppliers</span>
</div>
<div className="h-[2px] w-[340px] bg-gray-200">
<div className={`h-[2px] ${color}`} style={{ width: formatPercentage(value) }} />
</div>
</div>
</div>
);
};

export default BreakdownItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const SAMPLE_DATA = {
byMaterial: [
{ name: 'Supplier 1', value: 100 },
{ name: 'Supplier 1', value: 100 },
],
byOrigin: [
{ name: 'Supplier 1', value: 100, iso3: 'ITA' },
{ name: 'Supplier 1', value: 100, iso3: 'ITA' },
],
};

const DeforestationFreeSuppliersBreakdown = () => {
return <div>DeforestationFreeSuppliersBreakdown</div>;
};

export default DeforestationFreeSuppliersBreakdown;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const SuppliersWithDeforestationAlertsBreakdown = () => {
return <div>SuppliersWithDeforestationAlertsBreakdown</div>;
};

export default SuppliersWithDeforestationAlertsBreakdown;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const SuppliersWithNoLocationDataBreakdown = () => {
return <div>SuppliersWithNoLocationData</div>;
};

export default SuppliersWithNoLocationDataBreakdown;
101 changes: 101 additions & 0 deletions client/src/containers/analysis-eudr/category-list/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { useState } from 'react';

import DeforestationFreeSuppliersBreakdown from './breakdown/deforestation-free-suppliers';
import SuppliersWithDeforestationAlertsBreakdown from './breakdown/suppliers-with-deforestation-alerts';
import SuppliersWithNoLocationDataBreakdown from './breakdown/suppliers-with-no-location-data';

import { Button } from '@/components/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { formatPercentage } from '@/utils/number-format';

const CATEGORIES = [
{
name: 'Deforestation-free suppliers',
slug: 'deforestation-free-suppliers',
color: 'bg-[#4AB7F3]',
// todo move this value field to the component
value: 0.3,
},
{
name: 'Suppliers with deforestation alerts',
slug: 'suppliers-with-deforestation-alerts',
color: 'bg-[#FFC038]',
// todo move this value field to the component
value: 0.6,
},
{
name: 'Suppliers with no location data',
slug: 'suppliers-with-no-location-data',
color: 'bg-[#8460FF]',
// todo move this value field to the component
value: 0.1,
},
] as const;

type CategoryState = Record<(typeof CATEGORIES)[number]['slug'], boolean>;

export const CategoryList = (): JSX.Element => {
const [categories, toggleCategory] = useState<CategoryState>(
CATEGORIES.reduce(
(acc, category) => ({
...acc,
[category.slug]: false,
}),
{} as CategoryState,
),
);
const categoriesWithValues = CATEGORIES.map((category) => ({
...category,
// todo: calculate value field here
}));

return (
<>
{categoriesWithValues.map((category) => (
<Collapsible
key={category.slug}
className="rounded-xl bg-gray-50 p-5"
onOpenChange={() => {
toggleCategory((prev) => ({
...prev,
[category.slug]: !prev[category.slug],
}));
}}
>
<div className="flex w-full items-center space-x-6">
<div className="flex-1 text-left">{category.name}</div>
<div className="shrink-0 grow-0">
<div className="text-center">
{formatPercentage(category.value)} <span className="text-xs">of suppliers</span>
</div>
<div className="h-[2px] w-[340px] bg-gray-200">
<div
className={`h-[2px] ${category.color}`}
style={{ width: formatPercentage(category.value) }}
/>
</div>
</div>
<CollapsibleTrigger asChild>
<Button type="button" size="xs" variant="white">
{categories[category.slug] ? 'Close details' : 'View details'}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent>
{category.slug === 'deforestation-free-suppliers' && (
<DeforestationFreeSuppliersBreakdown />
)}
{category.slug === 'suppliers-with-deforestation-alerts' && (
<SuppliersWithDeforestationAlertsBreakdown />
)}
{category.slug === 'suppliers-with-no-location-data' && (
<SuppliersWithNoLocationDataBreakdown />
)}
</CollapsibleContent>
</Collapsible>
))}
</>
);
};

export default CategoryList;
Loading

0 comments on commit a86b72c

Please sign in to comment.