Skip to content

Commit

Permalink
update from main
Browse files Browse the repository at this point in the history
  • Loading branch information
Jocelyn2910 committed Apr 6, 2024
1 parent 46e2ba8 commit 446f6e1
Show file tree
Hide file tree
Showing 13 changed files with 833 additions and 128 deletions.
2 changes: 1 addition & 1 deletion webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 3 additions & 124 deletions webapp/src/app/(authenticated)/mflg/page.tsx
Original file line number Diff line number Diff line change
@@ -1,124 +1,3 @@
"use client"


import React, { useRef, useEffect, useState } from 'react';
import Boxplot from './components/boxplot';
import CurrentPrices from './components/currentprices';
import CurrentPricesMFLG from './components/currentprices-mflg';
import OptimisedPrices from './components/optimisedprice';
import DiscreteSlider from './components/slidebar'; // Import DiscreteSlider component
import BoxPlotLegend from './components/boxplot-legend';
import './pricebar.css';

interface ProductData {
prices: number[];
product_price: number;
ranking: number;
similar: number[];
}

function extractSimilarPrices(data: ProductData): { [key: string]: number } {
const prices: number[] = data.prices;
const similarIndices: number[] = data.similar;
const productPrice: number = data.product_price;
const extractedData: { [key: string]: number } = {};

// Loop through similar indices and extract corresponding prices
for (let i = 0; i < prices.length; i++) {
extractedData[similarIndices[i].toString()] = prices[i];
};

// Add the product price under the key 'mflg'
extractedData['mflg'] = productPrice;


return extractedData;
}



const PriceBar = () => {
const sample_similar_products: ProductData = {
"prices": [10.0, 12.0, 13.0, 24.5, 26.0, 40.0],
"product_price": 25.0,
"ranking": 0.82,
"similar": [3, 5, 6, 20, 35, 49]
};

const extractedData = extractSimilarPrices(sample_similar_products);

const svgRef = useRef<SVGSVGElement>(null);
// const [data,setData] = useState({ e: 10, a: 30, mflg: 40, z:40, aw:43.95, y:40, x:40, f: 53, g: 70, az:53, i: 90, j: 200 , ah:92.5, ab:90, ac:90, ad:200, ax:51});
const [data,setData] = useState(extractedData);
const [newData, setNewData] = useState({ k: 50 }); // State for newData
const [sliderValue, setSliderValue] = useState(50);// State for newData
const width = 500;
const height = 150;
const legendItems = [
{ label: 'MFLG product optimised price', color: 'red' },
{ label: 'MFLG product current price', color: 'green' },
{ label: 'Competitor product current price', color: 'steelblue' },
];

const handleSliderChange = (newValue: number) => {
setSliderValue(newValue);
};

const handleUpdateData = () => {

setData({});
setNewData({});

const svg = svgRef.current;
if (svg) {
while (svg.firstChild) {
svg.removeChild(svg.firstChild);
}
}
setData(extractedData);
// setData({ e: 10, a: 30, mflg: 40, z:40, aw:43.95, y:40, x:40, f: 53, g: 70, az:53, i: 90, j: 200 , ah:92.5, ab:90, ac:90, ad:200, ax:51});
setNewData({ k: sliderValue })
};

// const handleSliderChange = (newValue: number) => {
// setSliderValue(newValue);


// setData({});
// setNewData({});

// const svg = svgRef.current;
// if (svg) {
// while (svg.firstChild) {
// svg.removeChild(svg.firstChild);
// }
// }
// setData(extractedData);
// // setData({ e: 10, a: 30, mflg: 40, z:40, aw:43.95, y:40, x:40, f: 53, g: 70, az:53, i: 90, j: 200 , ah:92.5, ab:90, ac:90, ad:200, ax:51});
// setNewData({ k: newValue })
// };


return (
<div className="container">
<div className="boxplot-container">
<div className="content">
<div className="prices">
<h5>Slide to choose percentile</h5>
<div className="slider-button-container">
<DiscreteSlider handleChange={handleSliderChange} />
<button onClick={handleUpdateData}>Show optimised price</button>
</div>
<Boxplot data={data} svgRef={svgRef} width={width} height={height} />
<CurrentPrices data={data} svgRef={svgRef} width={width} height={height} />
<CurrentPricesMFLG data={data} svgRef={svgRef} width={width} height={height} />
<OptimisedPrices data={data} newData={newData} svgRef={svgRef} width={width} height={height}/>
<BoxPlotLegend legendItems={legendItems} />
</div>
</div>
</div>
</div>
);
}

export default PriceBar;
export default function Empty () {
return <h1>Empty!</h1>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.legend {
display: flex;
flex-direction: column;
}

.legend-item {
display: flex;
align-items: center;
margin-bottom: 5px;
}

.circle {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 5px;
}

.label {
font-size: 14px;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import './boxplot-legend.css';


interface LegendItem {
label: string;
color: string;
}

interface BoxPlotLegendProps {
legendItems: LegendItem[];
}

const BoxPlotLegend: React.FC<BoxPlotLegendProps> = ({ legendItems }) => {
return (
<div className="legend">
{legendItems.map((item, index) => (
<div key={index} className="legend-item">
<span className="circle" style={{ backgroundColor: item.color }}></span>
<span className="label">{item.label}</span>
</div>
))}
</div>
);
};

export default BoxPlotLegend;
141 changes: 141 additions & 0 deletions webapp/src/app/(authenticated)/pricebar/components/boxplot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"use client"

import React, { useEffect, useRef } from 'react';
import * as d3 from 'd3';

interface BoxPlotProps {
data: { [key: string]: number };
width: number;
height: number;
svgRef: React.MutableRefObject<SVGSVGElement | null>;
}

const BoxPlot: React.FC<BoxPlotProps> = ({ data, width, height, svgRef }) => {
useEffect(() => {
if (!svgRef.current) return;

const dataArray = Object.values(data);
if (dataArray.length === 0) return;

const margin = { top: 20, right: 50, bottom: 50, left: 2 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;

const svg = d3.select(svgRef.current)
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);

const yScale = d3.scaleBand()
.domain(['Box Plot'])
.range([margin.top, innerHeight])
.padding(0.1);

const xScale = d3.scaleLinear()
.domain([d3.min(dataArray)!, d3.max(dataArray)!])
.nice()
.range([margin.left, innerWidth]);

const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);

// Draw box plot
const boxPlotGroup = g.append('g');

const boxHeight = yScale.bandwidth();

Object.entries(data).forEach(([key, value]) => {
// For each key-value pair in the data object
boxPlotGroup.append('rect')
.attr('y', yScale('Box Plot') - 20)
.attr('x', xScale(d3.quantile(dataArray, 0.25)))
.attr('height', 40)
.attr('width', xScale(d3.quantile(dataArray, 0.75)) - xScale(d3.quantile(dataArray, 0.25)))
.attr('fill', 'rgba(0, 0, 0, 0.01)');
});


boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot') - 20)
.attr('y2', yScale('Box Plot') + 20)
.attr('x1', xScale(d3.quantile(dataArray, 0.5)))
.attr('x2', xScale(d3.quantile(dataArray, 0.5)))
.attr('stroke', 'black');

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot') - 20)
.attr('y2', yScale('Box Plot') + 20)
.attr('x1', xScale(d3.min(dataArray)!))
.attr('x2', xScale(d3.min(dataArray)!))
.attr('stroke', 'black')
.attr('stroke-width', 0.5)
.attr('stroke-dasharray', '3');

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot') - 20)
.attr('y2', yScale('Box Plot') + 20)
.attr('x1', xScale(d3.max(dataArray)!))
.attr('x2', xScale(d3.max(dataArray)!))
.attr('stroke', 'black')
.attr('stroke-width', 0.5)
.attr('stroke-dasharray', '3');

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot') - 20)
.attr('y2', yScale('Box Plot') + 20)
.attr('x1', xScale(d3.quantile(dataArray, 0.25)))
.attr('x2', xScale(d3.quantile(dataArray, 0.25)))
.attr('stroke', 'black')


boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot') - 20)
.attr('y2', yScale('Box Plot') + 20)
.attr('x1', xScale(d3.quantile(dataArray, 0.75)))
.attr('x2', xScale(d3.quantile(dataArray, 0.75)))
.attr('stroke', 'black')

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot'))
.attr('y2', yScale('Box Plot'))
.attr('x1', xScale(d3.min(dataArray)!))
.attr('x2', xScale(d3.quantile(dataArray, 0.25)))
.attr('stroke', 'black')

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot'))
.attr('y2', yScale('Box Plot'))
.attr('x1', xScale(d3.quantile(dataArray, 0.75)))
.attr('x2', xScale(d3.max(dataArray)!))
.attr('stroke', 'black')

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot')-20)
.attr('y2', yScale('Box Plot')-20)
.attr('x1', xScale(d3.quantile(dataArray, 0.25)))
.attr('x2', xScale(d3.quantile(dataArray, 0.75)))
.attr('stroke', 'black')

boxPlotGroup.append('line')
.attr('y1', yScale('Box Plot')+20)
.attr('y2', yScale('Box Plot')+20)
.attr('x1', xScale(d3.quantile(dataArray, 0.25)))
.attr('x2', xScale(d3.quantile(dataArray, 0.75)))
.attr('stroke', 'black')

const xAxis = d3.axisBottom(xScale);

g.append('g')
.attr('class', 'x-axis')
.call(xAxis)
.attr("transform", `translate(0, ${innerHeight})`);

}, [data, width, height, svgRef]);

return (
<svg ref={svgRef}></svg>
);
}

export default BoxPlot;
Loading

0 comments on commit 446f6e1

Please sign in to comment.