How to add data to an MUI table column-wise instead of row-wise? - material-ui

Good day! Here is the sandbox react code that I'm using for a project involving MUI tables:
I have been racking my brain over this, but can't seem to get a solution. How can I add to this table column-wise instead of by row?
In line 57-67, the rows are created first and then they are populated row-wise, left-to-right by data.
The data given looks like this:
const data = [
{name: "sample_name",
calories: "19",
fat: "90",
carbs: 70,
protein: 90},
{name: "sample_name",
calories: "19",
fat: "90",
carbs: 70,
protein: 90},
]
What the lines I mentioned do is it takes 1 of the objects in the data and appends them row-wise
I work with a data that looks like this:
const name = ["richard","nixon"]
const calories = [9, 9, 0, 9, 0, 5, 8]
const fat = [10, 9 , 9]
const carbs = [11, 3, 4,5 ]
const protein = [1, 1]
I just want to be able to insert name data into the name column... and so on... this should also hopefully make it easier for me to dynamically insert more data for each column using TextField+button action

Seems to me like this is a data issue, not Material UI. You need to provide row and column data to a table, regardless of what library you use, that's just how tables are build. So if you are getting back data by columns, you need a reducer or a method to convert them into rows. Here is a super quick and dirty example:
const rawData = {
name: ["Ice cream", "Sno cone"],
calories: [32, 45]
};
let columns = Object.keys(rawData);
let rows = rawData.name.map((name, i) => {
return { name, calories: rawData.calories[i] };
});
/*
rows = ["name", "calories"]
columns = [
{ name: "Ice cream", calories: 32 },
{ name: "Sno cone", calories: 45 },
];
*/
Obviously, this is a quick example and not very extensible, but should lead you in a good direction. Perhaps a reducer which could build out row data more elegantly. However, this will allow you to build out the table as intended:
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
{columns.map((i) => (
<TableCell>{i}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow key={row.name}>
<TableCell>{row.name}</TableCell>
<TableCell>{row.calories}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>

Related

Return nested data from recursive query

We have a list of recipes (recipe_id) and ingredients (ingredient_id). Every recipe can become an ingredient of another recipe and that child recipe can then hold more second level child recipes and so on. I need a recursive query that takes a recipe id (or an array of ids - how I have it setup now) and returns a NESTED table or array of all the ingredients of the main recipes and any child recipes.
We're using Postgresql / Supabase / PostgREST.
So far I've been able to create the recursive query as a RPC function that returns a table using UNION ALL. This gives me a flat table back and I can't definitively trace back an ingredient to a specific parent recipe (because the same recipe can be called as a child in multiple parent recipes). Not sure where to go from here? The only other option I've figured out so far is to have my API endpoint query each level one at a time, but it generates a lot of network requests =(
DESIRED OUTPUT
Super flexible on format, but it would be nice if I could get all the child components as a nested array like so:
[
{ id: 1,
recipe_id: 22,
item_id: 9,
item: "Croissant Dough",
...,
components: [
{ id: 2,
recipe_id: 1,
item_id: 33,
item: "Butter,
...,
components: []
},
{ id: 3,
recipe_id: 1,
item_id: 71,
item: "Wheat Flour",
...,
components: []
}
]
},
{ id: 1,
recipe_id: 29,
item_id: 4,
item: "Almond Filling",
...,
components: [
{ id: 2,
recipe_id: 29,
item_id: 16,
item: "Almond Meal,
...,
components: []
},
{ id: 3,
recipe_id: 29,
item_id: 42,
item: "Pastry Cream",
...,
components: [
{ id: 7,
recipe_id: 42,
item_id: 22,
item: "Egg Yolks",
...,
components: []
]
}
]
},
]
CURRENT RPC FUNCTION
CREATE or REPLACE FUNCTION recipe_components_recursive (recipeids text)
RETURNS TABLE (id int8, recipe_id int8, item_id int8, quantity numeric, unit_id int8, recipe_order int4, item text, visible bool, recipe bool, "unitName" varchar, "unitAbbreviation" varchar, "conversionFactor" float4, "metricUnit" int8, batch bool)
LANGUAGE plpgsql
AS $$
DECLARE
transformedjson int[] := recipeids;
BEGIN
RETURN QUERY
WITH RECURSIVE recipe_components_rec_query AS (
SELECT *
FROM recipe_components_items
WHERE recipe_components_items.recipe_id = ANY (transformedjson)
UNION ALL
SELECT o.id, o.recipe_id, o.item_id, o.quantity, o.unit_id, o.recipe_order, o.item, o.visible, o.recipe, o."unitName", o."unitAbbreviation", o."conversionFactor", o."metricUnit", o.batch
FROM recipe_components_items o
INNER JOIN recipe_components_rec_query n ON n.item_id = o.recipe_id AND n.recipe = true
) SELECT *
FROM recipe_components_rec_query;
END $$;

React Material Data Grid: Sorting a currency field

I am passing in rows of financial data to a React MUI Data Grid component, however, as a currency symbol exists within the cell data the default sorting function is not working. Is there anyway I can ignore the currency symbol when applying sort?
[
{id: 0, cpa: '£20', cpl: '£0', revshare: '0%', startDate: '02/03/2022'}
{id: 1, cpa: '£10', cpl: '£0', revshare: '0%', startDate: '02/02/2022'}
]
<DataGrid
disableSelectionOnClick
headerHeight={65}
rowHeight={70}
autoHeight
className={classes.root}
rows={displayRowData(rowsData)}
columns={columns}
/>
You can add a custom sortComparator in the columns of your <DataGrid/>.
Assuming your currency symbol is always the first character, your cpa column definition would look like this:
const columns = [
...
{
field: "cpa",
headerName: "cpa",
sortComparator: (a: string, b: string) =>
Number(a.slice(1)) - Number(b.slice(1)),
},
...
];
For more information regarding sorting I would recommend checking out the official documentation.

Sort a map within a map and convert to list within a list

Here's my data in Firebase:
prices
price1
priceAmount1: 10
priceAmount2: 20
priceAmount3: 30
price2
priceAmount1: 15
priceAmount2: 5
priceAmount3: 7
price3
priceAmount1: 2
priceAmount2: 4
priceAmount3: 6
If I straight away retrieve it. Sometimes the ordering is price2, price3, price1. So I tried sorting it like this:
var sortedKeys = prices!.price!.keys.toList()..sort();
for (var it = 0; it < sortedKeys.length; it++) {
print('${sortedKeys[it]}');
}
But since it becomes a list, I'm not able to access the map anymore. I wanted to sort the map within a map then store it in a list within a list. Please help. Thanks!
Edit:
final splayByPrice =
SplayTreeMap<dynamic, dynamic>((a, b) => a.compareTo(b));
List<Map<dynamic, dynamic>> priceAmountMap = [
{
'priceAmount1': 10,
'priceAmount2': 20,
'priceAmount3': 30,
},
{
'priceAmount1': 15,
'priceAmount2': 5,
'priceAmount3': 7,
},
{
'priceAmount1': 2,
'priceAmount2': 4,
'priceAmount3': 6,
}
];
Map<dynamic, Map<dynamic, dynamic>> priceMap = {
'price2': priceAmountMap[1],
'price1': priceAmountMap[0],
'price3': priceAmountMap[2],
};
priceMap.forEach((key, value) {
splayByPrice.addAll(value);
});
priceMap.forEach((key, value) {
print('$key \t $value');
});
What it prints, is still not sorted.
price2 {priceAmount1: 15, priceAmount2: 5, priceAmount3: 7}
price1 {priceAmount1: 10, priceAmount2: 20, priceAmount3: 30}
price3 {priceAmount1: 2, priceAmount2: 4, priceAmount3: 6}
Dart's default Map implementation is a LinkedHashMap that stores entries in order of insertion.
(You haven't provided code that clearly shows your data structure, so I'll use my own example.)
If you want the Map to be sorted by the keys' alphabetic order, then you could:
Create a new Map, adding items to it in the desired order:
var theMap = {
4: 'four',
7: 'seven',
6: 'six',
9: 'nine',
5: 'five',
1: 'one',
8: 'eight',
0: 'zero',
3: 'three',
2: 'two',
};
void main() {
var sortedKeys = theMap.keys.toList()..sort();
var sortedMap = {
for (var key in sortedKeys)
key: theMap[key]!,
};
print(sortedMap);
}
Update the existing Map, removing and re-adding items in the desired order:
void main() {
var sortedKeys = theMap.keys.toList()..sort();
for (var key in sortedKeys) {
var value = theMap[key]!;
theMap.remove(key);
theMap[key] = value;
}
print(theMap);
}
Use a SplayTreeMap, which keeps entries sorted by a comparison rule.
import 'dart:collection';
void main() {
var splayTreeMap = SplayTreeMap.of(theMap);
print(splayTreeMap);
}
If you need to sort the data only once, I'd use one of the first two methods. If you're frequently adding new entries, then I'd use a SplayTreeMap instead of a Map/LinkedHashMap so that entries are kept in a sorted order. (But note that lookups, insertions, and removals in a SplayTreeMap are O(log n) instead of O(1).)
Also, if you're sorting strings that contain numbers, you probably don't want to use the normal string sort.

Finding the sum of all values in a List of maps in Flutter

So I have a List of Maps of two dynamic variables.
[{Title: product 1, Item Score: 87.3, Characters: 72, Image Count: 6},
{Title: product 2, Item Score: 85.1, Characters: 56, Image Count: 2}]
How would I add up all of them item scores? There are more items than this in the full file.
I would look at fold in the standard library https://api.dart.dev/stable/1.10.1/dart-core/List/fold.html.
With fold, you iterate over the list of maps, and the first argument is your starting value. In the case of sum, this would be 0. Your inner function in the fold takes 2 arguments, the current accumlation(sum), and the item in your list that is currently being iterated over.
E.g.:
const itemScores = [{'itemScore': 1}, {'itemScore': 2}, {'itemScore': 44}];
var sum = itemScores.fold(0, (i, el){
return i + el['itemScore'];
});
Where i is the current value of the accumulator, and el is the current item in the list being iterated over.
Assuming that, you need to store the value in some variable, you can simply use List.forEach((element){ })
Advantage, you can iterate over as many data as you can, and then store the value
void main(){
var data = [{"Title": "product 1", "Item Score": 87.3, "Characters": 72, "Image Count": 6}, {"Title": "product 2", "Item Score": 85.1, "Characters": 56, "Image Count": 2}];
double totalScores = 0.0;
// looping over data array
data.forEach((item){
//getting the key direectly from the name of the key
totalScores += item["Item Score"];
});
print(totalScores); // OUTPUT ==> 172.39999999999998
}
List arr = [[1,2,3],[4,5,7],[8,9,10],[14,15,19]];
int stairsIn203(List<List<int>> arr) {
// your code here
int _a = 0 ;
List _b = [];
for(List i in arr){
_b += i;
}
_a = _b.reduce((value, element) => value + element) * 20;
return _a;
}
Or
int stairsIn20(List<List<int>> arr) => arr.expand((e) => e).reduce((v, e) => v + e) * 20;
var sum = [{Title: product 1, Item Score: 87.3, Characters: 72, Image
Count: 6}, {Title: product 2, Item Score: 85.1, Characters: 56, Image
Count: 2}]].reduce((item1, item2) => item1["Item Score"] +item2["Item
Score"]);

Elastic/Nearest search based on document properties in MongoDB

We need to accomplish the nearest search based on document properties in MongoDB.
Let's take an example, there is a Car schema in MongoDB, information will be stored as something similar to:
{
Make: "Hyundai",
Model: "Creta",
Title: "Hyundai Creta E 1.6 Petrol",
Description: "Compact SUV",
Feature: {
ABS: true,
EBD: true,
Speakers: 4,
Display: false
},
Specification: {
Length: "4270 mm",
Width: "1780 mm",
Height: "1630 mm",
Wheelbase: "2590 mm",
Doors: 5,
Seating: 5,
Displacement: "1591 cc"
},
Safety: {
Airbags: 2,
SeatBeltWarning: false
},
Maintenance: {
LastService: "21/06/2016",
WashingDone: true
}
}
Search needs to be provided based on following criteria:
1. Make
2. Model
3. ABS
4. Seating
5. Displacement
6. Airbags
Now results should contain records where 3 or more of the properties match (exact match), and ordered based on the maximum number of properties that match.
What is the best way to implement this with MongoDB?
You could write something to generate documents for each triplet of fields, and then put them together with $or, producing something like
{$or: [
{Make: "Hyundai", Model: "Creta", Feature.ABS: true},
{Make: "Hyundai", Model: "Creta", Specification.Seating: 5},
...
]}
Sorting probably requires sorting by textScore.