converted frontend from tailwind to material-ui using AI

main
avraham 9 months ago
parent 3e5e728d92
commit 70b690ab9d

@ -1,7 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root { :root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5; line-height: 1.5;

@ -7,20 +7,25 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@date-io/date-fns": "^3.0.0",
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@mui/material": "^5.16.6",
"@mui/system": "^5.16.6",
"@mui/x-date-pickers": "^7.12.0",
"@preact/signals": "^1.2.2", "@preact/signals": "^1.2.2",
"@trpc/client": "^10.45.0", "@trpc/client": "^10.45.0",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"date-fns": "^3.6.0",
"dotenv": "^16.4.1", "dotenv": "^16.4.1",
"preact": "^10.13.1", "preact": "^10.13.1",
"preact-iso": "^2.3.2", "preact-iso": "^2.3.2",
"preact-render-to-string": "^6.3.1", "preact-render-to-string": "^6.3.1",
"react": "18.3.1",
"react-chartjs-2": "^5.2.0" "react-chartjs-2": "^5.2.0"
}, },
"devDependencies": { "devDependencies": {
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite": "^4.3.2" "vite": "^4.3.2"
} }

File diff suppressed because it is too large Load Diff

@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

@ -1,27 +1,40 @@
import { useLocation } from "preact-iso"; import { useLocation } from "preact-iso";
import { AppBar, Toolbar, Button, Box } from "@mui/material";
import { styled } from "@mui/system";
const StyledToolbar = styled(Toolbar)({
display: "flex",
justifyContent: "center",
backgroundColor: "#E0E7FF", // Indigo-200 equivalent
});
const StyledButton = styled(Button)(({ theme, active }) => ({
color: theme.palette.text.primary,
fontWeight: active ? "bold" : "normal",
textDecoration: active ? "underline" : "none",
}));
export function Header() { export function Header() {
const { url } = useLocation(); const { url } = useLocation();
return ( return (
<header class="flex flex-row justify-center"> <AppBar position="static" elevation={0}>
<nav class="flex flex-row justify-center text-lg gap-4 max-w-5xl py-2 px-3 rounded-full bg-indigo-200"> <StyledToolbar>
<a <Box sx={{ display: "flex", gap: 2 }}>
href="/" <StyledButton
class={ href="/"
(url === "/" || url === "/historical-calendar-prices") && active={url === "/" || url === "/historical-calendar-prices"}
"underline font-bold" >
} Historical Calendar Prices
> </StyledButton>
Historical Calendar Prices <StyledButton
</a> href="/calendar-optimizer"
<a active={url === "/calendar-optimizer"}
href="/calendar-optimizer" >
class={url === "/calendar-optimizer" && "underline font-bold"} Calendar Optimizer
> </StyledButton>
Calendar Optimizer </Box>
</a> </StyledToolbar>
</nav> </AppBar>
</header>
); );
} }

@ -1,31 +1,36 @@
import _ from "./env";
import { render } from "preact"; import { render } from "preact";
import { LocationProvider, Router, Route } from "preact-iso"; import { LocationProvider, Router, Route } from "preact-iso";
import { ThemeProvider, createTheme } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { Header } from "./components/Header.jsx"; import { Header } from "./components/Header.jsx";
import { CalendarOptimizer } from "./pages/CalendarOptimizer.js"; import { CalendarOptimizer } from "./pages/CalendarOptimizer.js";
import { NotFound } from "./pages/_404.jsx"; import { NotFound } from "./pages/_404.jsx";
// import './style.css';
import { HistoricalCalendarPrices } from "./pages/HistoricalCalendarPrices.js"; import { HistoricalCalendarPrices } from "./pages/HistoricalCalendarPrices.js";
const theme = createTheme();
export function App() { export function App() {
return ( return (
<LocationProvider> <ThemeProvider theme={theme}>
<div class="flex flex-col justify-start gap-4"> <CssBaseline />
<Header /> <LocationProvider>
<main> <div>
<Router> <Header />
<Route path="/" component={HistoricalCalendarPrices} /> <main>
<Route path="/calendar-optimizer" component={CalendarOptimizer} /> <Router>
<Route <Route path="/" component={HistoricalCalendarPrices} />
path="/historical-calendar-prices" <Route path="/calendar-optimizer" component={CalendarOptimizer} />
component={HistoricalCalendarPrices} <Route
/> path="/historical-calendar-prices"
<Route default component={NotFound} /> component={HistoricalCalendarPrices}
</Router> />
</main> <Route default component={NotFound} />
</div> </Router>
</LocationProvider> </main>
</div>
</LocationProvider>
</ThemeProvider>
); );
} }

@ -10,7 +10,16 @@ import {
Title, Title,
} from "chart.js"; } from "chart.js";
import { Scatter } from "react-chartjs-2"; import { Scatter } from "react-chartjs-2";
// import "./style.css"; import {
Container,
Grid,
Typography,
FormControl,
InputLabel,
Select,
MenuItem,
Paper,
} from "@mui/material";
ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title); ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title);
@ -114,98 +123,86 @@ export function CalendarOptimizer() {
useEffect(handleInit, []); useEffect(handleInit, []);
return ( return (
/* container for centering: */ <Container maxWidth="lg">
<div class="flex flex-row justify-center"> <Grid container spacing={4}>
<div class="flex flex-col justify-start gap-4"> <Grid item xs={12}>
{/* inputs form container: */} <Typography variant="h4" gutterBottom>
<div class="flex flex-col justify-start gap-1"> Calendar Optimizer
<div class="flex flex-row w-160 gap-3"> </Typography>
<div class="text-right w-1/3"> </Grid>
<label>Available Underlyings</label> <Grid item xs={12} md={6}>
</div> <Paper elevation={3} sx={{ p: 3 }}>
<div class="my-auto w-2/3"> <Grid container spacing={2}>
{availableUnderlyings.value.length === 0 ? ( <Grid item xs={12}>
"Loading..." <FormControl fullWidth>
) : ( <InputLabel>Available Underlyings</InputLabel>
<select <Select
onChange={handleUnderlyingChange} value={chosenUnderlying.value || ""}
class="border border-gray-300 focus:border-blue-400" onChange={handleUnderlyingChange}
> label="Available Underlyings"
{availableUnderlyings.value.map((availableUnderlying) => ( >
<option value={availableUnderlying}> {availableUnderlyings.value.map((underlying) => (
{availableUnderlying} <MenuItem key={underlying} value={underlying}>
</option> {underlying}
))} </MenuItem>
</select> ))}
)} </Select>
</div> </FormControl>
</div> </Grid>
<div class="flex flex-row w-160 gap-3"> <Grid item xs={12}>
<div class="text-right w-1/3"> <FormControl fullWidth>
<label>Available "As-of" Dates</label> <InputLabel>Available "As-of" Dates</InputLabel>
</div> <Select
<div class="my-auto w-2/3"> value={chosenAsOfDate.value || ""}
{availableAsOfDates.value.length === 0 ? ( onChange={handleAsOfDateChange}
"Loading..." label='Available "As-of" Dates'
) : ( >
<select {availableAsOfDates.value.map((asOfDate) => (
onChange={handleAsOfDateChange} <MenuItem key={asOfDate} value={asOfDate}>
class="border border-gray-300 focus:border-blue-400" {asOfDate}
> </MenuItem>
{availableAsOfDates.value.map((availableAsOfDate) => ( ))}
<option value={availableAsOfDate}> </Select>
{availableAsOfDate} </FormControl>
</option> </Grid>
))} <Grid item xs={12}>
</select> <FormControl fullWidth>
)} <InputLabel>Available Expirations</InputLabel>
</div> <Select
</div> value={chosenExpiration.value || ""}
<div class="flex flex-row w-160 gap-3"> onChange={handleExpirationChange}
<div class="text-right w-1/3"> label="Available Expirations"
<label>Available Expirations</label> >
</div> {availableExpirations.value.map((expiration) => (
<div class="my-auto w-2/3"> <MenuItem key={expiration} value={expiration}>
{availableExpirations.value.length === 0 ? ( {expiration}
"Loading..." </MenuItem>
) : ( ))}
<select </Select>
onChange={handleExpirationChange} </FormControl>
class="border border-gray-300 focus:border-blue-400" </Grid>
> <Grid item xs={12}>
{availableExpirations.value.map((availableExpiration) => ( <FormControl fullWidth>
<option value={availableExpiration}> <InputLabel>Available Strikes</InputLabel>
{availableExpiration} <Select
</option> value={chosenStrike.value || ""}
))} onChange={handleStrikeChange}
</select> label="Available Strikes"
)} >
</div> {availableStrikes.value.map((strike) => (
</div> <MenuItem key={strike} value={strike}>
<div class="flex flex-row w-160 gap-3"> {strike}
<div class="text-right w-1/3"> </MenuItem>
<label>Available Strikes</label> ))}
</div> </Select>
<div class="my-auto w-2/3"> </FormControl>
{availableStrikes.value.length === 0 ? ( </Grid>
"Loading..." </Grid>
) : ( </Paper>
<select </Grid>
onChange={handleStrikeChange} <Grid item xs={12} md={6}>
class="border border-gray-300 focus:border-blue-400" <Paper elevation={3} sx={{ p: 3, height: '100%' }}>
> {chosenUnderlying.value !== null && underlyingUplotData.value.length > 0 ? (
{availableStrikes.value.map((availableStrike) => (
<option value={availableStrike}>{availableStrike}</option>
))}
</select>
)}
</div>
</div>
</div>
<div className="chart-container">
{chosenUnderlying.value !== null &&
underlyingUplotData.value.length > 0 ? (
<div className="chart">
<Scatter <Scatter
data={{ data={{
datasets: [ datasets: [
@ -229,8 +226,6 @@ export function CalendarOptimizer() {
.substring(0, 10); .substring(0, 10);
}, },
}, },
// min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
// max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
}, },
y: { y: {
beginAtZero: false, beginAtZero: false,
@ -239,8 +234,6 @@ export function CalendarOptimizer() {
return "$" + value.toString(); return "$" + value.toString();
}, },
}, },
// min: 0,
// max: maxChartPrice.value,
}, },
}, },
elements: { elements: {
@ -265,16 +258,18 @@ export function CalendarOptimizer() {
maintainAspectRatio: false, maintainAspectRatio: false,
}} }}
/> />
</div> ) : (
) : ( <Typography>Loading Chart...</Typography>
<></> )}
)} </Paper>
{chosenUnderlying.value !== null && </Grid>
chosenAsOfDate.value !== null && <Grid item xs={12}>
chosenExpiration.value !== null && <Paper elevation={3} sx={{ p: 3 }}>
chosenStrike.value !== null && {chosenUnderlying.value !== null &&
optionContractUplotData.value.length > 0 ? ( chosenAsOfDate.value !== null &&
<div className="chart"> chosenExpiration.value !== null &&
chosenStrike.value !== null &&
optionContractUplotData.value.length > 0 ? (
<Scatter <Scatter
data={{ data={{
datasets: [ datasets: [
@ -298,8 +293,6 @@ export function CalendarOptimizer() {
.substring(0, 10); .substring(0, 10);
}, },
}, },
// min: (new Date(chosenLookbackPeriodStart.value)).getTime()/1000,
// max: (new Date(chosenLookbackPeriodEnd.value)).getTime()/1000,
}, },
y: { y: {
beginAtZero: false, beginAtZero: false,
@ -308,8 +301,6 @@ export function CalendarOptimizer() {
return "$" + value.toString(); return "$" + value.toString();
}, },
}, },
// min: 0,
// max: maxChartPrice.value,
}, },
}, },
elements: { elements: {
@ -334,12 +325,12 @@ export function CalendarOptimizer() {
maintainAspectRatio: false, maintainAspectRatio: false,
}} }}
/> />
</div> ) : (
) : ( <Typography>Loading Chart...</Typography>
<></> )}
)} </Paper>
</div> </Grid>
</div> </Grid>
</div> </Container>
); );
} }

@ -10,7 +10,17 @@ import {
Title, Title,
} from "chart.js"; } from "chart.js";
import { Scatter } from "react-chartjs-2"; import { Scatter } from "react-chartjs-2";
// import './style.css'; import {
Container,
Grid,
Typography,
TextField,
Select,
MenuItem,
InputLabel,
FormControl,
Paper,
} from "@mui/material";
ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title); ChartJS.register(LinearScale, CategoryScale, PointElement, Tooltip, Title);
@ -188,122 +198,109 @@ export function HistoricalCalendarPrices() {
useEffect(handleInit, []); useEffect(handleInit, []);
return ( return (
/* container for centering: */ <Container maxWidth="lg">
<div class="flex flex-row justify-center"> <Grid container spacing={4}>
<div class="flex flex-col justify-start gap-4"> <Grid item xs={12}>
{/* inputs form container: */} <Typography variant="h4" gutterBottom>
<div class="flex flex-col justify-start gap-1 divide-y"> Historical Calendar Prices
<div class="flex flex-row w-160 gap-3"> </Typography>
<div class="text-right w-1/3"> </Grid>
<label>Available Underlyings</label> <Grid item xs={12} md={6}>
</div> <Paper elevation={3} sx={{ p: 3 }}>
<div class="my-auto w-2/3"> <Grid container spacing={2}>
{availableUnderlyings.value.length === 0 ? ( <Grid item xs={12}>
"Loading..." <FormControl fullWidth>
) : ( <InputLabel>Available Underlyings</InputLabel>
<select <Select
onChange={handleUnderlyingChange} value={chosenUnderlying.value || ""}
class="border border-gray-300 focus:border-blue-400" onChange={handleUnderlyingChange}
> label="Available Underlyings"
{availableUnderlyings.value.map((availableUnderlying) => ( >
<option value={availableUnderlying}> {availableUnderlyings.value.map((underlying) => (
{availableUnderlying} <MenuItem key={underlying} value={underlying}>
</option> {underlying}
))} </MenuItem>
</select> ))}
)} </Select>
</div> </FormControl>
</div> </Grid>
<div class="flex flex-row w-160 gap-3"> <Grid item xs={12}>
<div class="text-right w-1/3"> <TextField
<label>Now-to-Front-Month "Days to Expiration"</label> fullWidth
</div> label="Now-to-Front-Month Days to Expiration"
<div class="my-auto w-2/3"> type="number"
<input value={chosenDaysToFrontExpiration.value}
type="text" onChange={handleDaysToFrontExpirationChange}
onBlur={handleDaysToFrontExpirationChange} InputProps={{ endAdornment: "Days" }}
value={chosenDaysToFrontExpiration.value} />
class="border border-gray-300 focus:border-blue-400" </Grid>
/> <Grid item xs={12}>
Days <TextField
</div> fullWidth
</div> label="Front-to-Back-Month Days to Expiration Difference"
<div class="flex flex-row w-160 gap-3"> type="number"
<div class="text-right w-1/3"> value={chosenDaysBetweenFrontAndBackExpiration.value}
<label>Front-to-Back-Month "Days to Expiration" Difference</label> onChange={handleDaysBetweenFrontAndBackExpirationChange}
</div> InputProps={{ endAdornment: "Days Difference" }}
<div class="my-auto w-2/3"> />
<input </Grid>
type="text" <Grid item xs={6}>
onBlur={handleDaysBetweenFrontAndBackExpirationChange} <TextField
value={chosenDaysBetweenFrontAndBackExpiration.value} fullWidth
class="border border-gray-300 focus:border-blue-400" label="Strike % From Underlying Price"
/> type="number"
Days Difference value={chosenStrikePercentageFromUnderlyingPrice.value}
</div> onChange={handleStrikePercentageFromUnderlyingPriceChange}
</div> InputProps={{ endAdornment: "%" }}
<div class="flex flex-row w-160 gap-3"> />
<div class="text-right w-1/3"> </Grid>
<label>"Strike Percentage From Underlying Price" Range</label> <Grid item xs={6}>
</div> <TextField
<div class="my-auto w-2/3"> fullWidth
<input label="Strike % Radius"
type="text" type="number"
onBlur={handleStrikePercentageFromUnderlyingPriceChange} value={chosenStrikePercentageFromUnderlyingPriceRadius.value}
value={chosenStrikePercentageFromUnderlyingPrice.value} onChange={handleStrikePercentageFromUnderlyingPriceRadiusChange}
class="border border-gray-300 focus:border-blue-400" InputProps={{ endAdornment: "%" }}
/> />
% +/- </Grid>
<input <Grid item xs={12}>
type="text" <TextField
onBlur={handleStrikePercentageFromUnderlyingPriceRadiusChange} fullWidth
value={chosenStrikePercentageFromUnderlyingPriceRadius.value} label="Exit-to-Front-Month Days to Expiration"
class="border border-gray-300 focus:border-blue-400" type="number"
/> value={chosenExitToFrontExpiration.value}
% from ATM onChange={handleExitToFrontExpirationChange}
</div> InputProps={{ endAdornment: "Days" }}
</div> />
<div class="flex flex-row w-160 gap-3"> </Grid>
<div class="text-right w-1/3"> <Grid item xs={6}>
<label>Exit-to-Front-Month "Days to Expiration"</label> <TextField
</div> fullWidth
<div class="my-auto w-2/3"> label="Lookback Period Start"
<input type="date"
type="text" value={chosenLookbackPeriodStart.value}
onBlur={handleExitToFrontExpirationChange} onChange={(e) => handleLookbackPeriodStartChange({ target: { value: e.target.value } })}
value={chosenExitToFrontExpiration.value} InputLabelProps={{ shrink: true }}
class="border border-gray-300 focus:border-blue-400" />
/> </Grid>
Days <Grid item xs={6}>
</div> <TextField
</div> fullWidth
<div class="flex flex-row w-160 gap-3"> label="Lookback Period End"
<div class="text-right w-1/3"> type="date"
<label>Lookback Period</label> value={chosenLookbackPeriodEnd.value}
</div> onChange={(e) => handleLookbackPeriodEndChange({ target: { value: e.target.value } })}
<div class="my-auto w-2/3"> InputLabelProps={{ shrink: true }}
<input />
type="text" </Grid>
onBlur={handleLookbackPeriodStartChange} </Grid>
value={chosenLookbackPeriodStart.value} </Paper>
class="border border-gray-300 focus:border-blue-400" </Grid>
/> <Grid item xs={12} md={6}>
- <Paper elevation={3} sx={{ p: 3, height: '100%' }}>
<input {chosenUnderlying.value !== null &&
type="text" historicalStockQuoteChartData.value.length > 0 ? (
onBlur={handleLookbackPeriodEndChange}
value={chosenLookbackPeriodEnd.value}
class="border border-gray-300 focus:border-blue-400"
/>
</div>
</div>
</div>
{/* charts container: */}
<div className="flex flex-col justify-start gap-3">
<div className="min-h-96">
{chosenUnderlying.value !== null &&
historicalStockQuoteChartData.value.length > 0 ? (
<div className="h-full">
<Scatter <Scatter
data={{ data={{
datasets: [ datasets: [
@ -366,15 +363,15 @@ export function HistoricalCalendarPrices() {
events: [], events: [],
}} }}
/> />
</div> ) : (
) : ( <Typography>Loading Chart...</Typography>
<div className="h-full">Loading Chart...</div> )}
)} </Paper>
</div> </Grid>
<div className="min-h-96"> <Grid item xs={12}>
{chosenUnderlying.value !== null && <Paper elevation={3} sx={{ p: 3 }}>
historicalCalendarQuoteChartData.value.length > 0 ? ( {chosenUnderlying.value !== null &&
<div className="h-full"> historicalCalendarQuoteChartData.value.length > 0 ? (
<Scatter <Scatter
data={{ data={{
datasets: [ datasets: [
@ -433,15 +430,15 @@ export function HistoricalCalendarPrices() {
events: [], events: [],
}} }}
/> />
</div> ) : (
) : ( <Typography>Loading Chart...</Typography>
<div className="h-full">Loading Chart...</div> )}
)} </Paper>
</div> </Grid>
<div className="min-h-96"> <Grid item xs={12}>
{chosenUnderlying.value !== null && <Paper elevation={3} sx={{ p: 3 }}>
historicalCalendarQuoteChartData.value.length > 0 ? ( {chosenUnderlying.value !== null &&
<div className="h-full"> historicalCalendarQuoteChartData.value.length > 0 ? (
<Scatter <Scatter
data={{ data={{
datasets: [ datasets: [
@ -509,13 +506,12 @@ export function HistoricalCalendarPrices() {
events: [], events: [],
}} }}
/> />
</div> ) : (
) : ( <Typography>Loading Chart...</Typography>
<div className="h-full">Loading Chart...</div> )}
)} </Paper>
</div> </Grid>
</div> </Grid>
</div> </Container>
</div>
); );
} }

@ -1,13 +0,0 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
width: {
128: "32rem",
160: "40rem",
},
},
},
plugins: [],
};
Loading…
Cancel
Save