From 24d122c2cc78bb97bf7a27b158c8ec4c7c0b7ac0 Mon Sep 17 00:00:00 2001 From: James Croft Date: Wed, 4 Dec 2024 12:23:36 +0000 Subject: [PATCH 1/3] Refactor UX into dedicated components --- src/App.jsx | 355 +----------------- .../calculator/CalculationExplanation.jsx | 59 +++ src/components/calculator/Calculator.jsx | 35 ++ .../calculator/CalculatorOutput.jsx | 123 ++++++ src/components/calculator/ImageEditor.jsx | 88 +++++ src/components/calculator/ModelSelector.jsx | 46 +++ src/components/layout/Footer.jsx | 41 ++ 7 files changed, 400 insertions(+), 347 deletions(-) create mode 100644 src/components/calculator/CalculationExplanation.jsx create mode 100644 src/components/calculator/Calculator.jsx create mode 100644 src/components/calculator/CalculatorOutput.jsx create mode 100644 src/components/calculator/ImageEditor.jsx create mode 100644 src/components/calculator/ModelSelector.jsx create mode 100644 src/components/layout/Footer.jsx diff --git a/src/App.jsx b/src/App.jsx index 771c38a..c2deb81 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,71 +1,11 @@ -import { useState } from "react"; import { ThemeProvider } from "@mui/material/styles"; import theme from "./components/layout/Theme"; -import { - Container, - TextField, - Button, - Typography, - MenuItem, - Select, - InputLabel, - FormControl, - IconButton, - Grid2 as Grid, - Accordion, - AccordionSummary, - AccordionDetails, - Box, -} from "@mui/material"; -import { Add, Delete, FileCopy, GitHub, LinkedIn } from "@mui/icons-material"; -import { useBoundStore } from "./stores"; +import Calculator from "./components/calculator/Calculator"; +import CalculationExplanation from "./components/calculator/CalculationExplanation"; +import Footer from "./components/layout/Footer"; +import { Container, Typography, Grid2 as Grid } from "@mui/material"; function App() { - const [modelName, setModelName] = useState(""); - - const images = useBoundStore((state) => state.images); - const models = useBoundStore((state) => state.models); - const setModel = useBoundStore((state) => state.setModel); - const addImage = useBoundStore((state) => state.addImage); - const updateImage = useBoundStore((state) => state.updateImage); - const removeImage = useBoundStore((state) => state.removeImage); - const runCalculation = useBoundStore((state) => state.runCalculation); - const resetCalculation = useBoundStore((state) => state.resetCalculation); - const totalTokens = useBoundStore((state) => state.totalTokens); - const totalCost = useBoundStore((state) => state.totalCost); - const model = useBoundStore((state) => state.model); - - const selectModel = (model) => { - setModelName(model); - - const selectedModel = models.find((m) => m.name === model); - if (selectedModel) { - setModel(selectedModel); - runCalculation(); - } else { - setModel(null); - resetCalculation(); - } - }; - - const addNewImage = () => { - addImage({ height: 0, width: 0, multiplier: 1 }); - }; - - const cloneImage = (index) => { - const image = images[index]; - addImage({ - height: image.height, - width: image.width, - multiplier: image.multiplier, - }); - }; - - const handleSubmit = (event) => { - event.preventDefault(); - runCalculation(); - }; - return ( @@ -74,291 +14,12 @@ function App() { -
- - Model - - - - {images.map((image, index) => ( - - - - updateImage(index, "height", e.target.value) - } - margin="normal" - required - fullWidth - /> - - - - updateImage(index, "width", e.target.value) - } - margin="normal" - required - fullWidth - /> - - - - updateImage(index, "multiplier", e.target.value) - } - margin="normal" - required - fullWidth - /> - - - cloneImage(index)} - color="primary" - > - - - - - removeImage(index)} - color="secondary" - > - - - - - ))} - - - - -
- - - {images.map((image, index) => - image.resizedHeight ? ( - - - - Image {index + 1} - - - - - Resized Size - - - {image.resizedHeight} x {image.resizedWidth} - - - - - Tiles (per image) - - - {image.tilesHigh} x {image.tilesWide} - - - - - Total tiles - - - {image.totalTiles} - - - - - - ) : null - )} - - {totalTokens !== null && ( - - - - Result - - - {model && ( - - - Base tokens - - - {model.baseTokens} - - - )} - - {model && ( - - - Tile tokens - - - {model.tokensPerTile} x{" "} - {images - .map((image) => image.totalTiles ?? 0) - .reduce((acc, val) => acc + val, 0)}{" "} - = {totalTokens - model.baseTokens} - - - )} - - {totalTokens !== null && ( - - - Total tokens - - - {totalTokens} - - - )} - - {totalCost !== null && ( - - - Total cost - - - ${totalCost} - - - )} - - - - )} - +
- - - - How the Calculation Works - - {model ? ( - - -

The calculation involves several steps:

-
- - 1. Resizing Images: Ensure each image is resized to - fit within the maximum dimension {model.maxImageDimension} - px, and has at least {model.imageMinSizeLength}px on the - shortest side, while maintaining its aspect ratio. - - - 2. Calculating Tiles: The resized image is divided - into tiles based on the model's tile size of{" "} - {model.tileSizeLength}px by {model.tileSizeLength}px. - - - 3. Token Calculation: The total number of tokens is - calculated by multiplying the number of tiles by the tokens - per tile ({model.tokensPerTile}) and adding{" "} - {model.baseTokens} base tokens. - - - 4. Cost Calculation: The total cost is calculated - based on the total number of tokens and the cost per - thousand tokens (${model.costPerThousandTokens}). - -
- ) : ( - - - Please select a model to see the calculation explanation. - - - )} -
- - Created by James Croft. - - - - - + + +