DOING: convert full site to MUI...
npm easy-peasy
import { createTypedHooks } from 'easy-peasy';import { StoreModel } from './store';const typedHooks = createTypedHooks<StoreModel>();export const useStoreActions = typedHooks.useStoreActions;export const useStoreDispatch = typedHooks.useStoreDispatch;export const useStoreState = typedHooks.useStoreState;
import { useStoreState, useStoreActions } from "../hooks";import { FaRegTrashCan } from "react-icons/fa6";export const PageWelcome = () => {const flashcards = useStoreState((state) => state.flashcards);const deleteFlashcard = useStoreActions((actions) => actions.deleteFlashcard);return (<><p>There are {flashcards.length} flashcards.</p><ul className="list-disc ml-6">{flashcards.map((flashcard, index) => {return (<li><div className="mt-2 flex gap-2" key={index}>{flashcard.front} - {flashcard.back} <FaRegTrashCan className="mt-1 hover:text-red-800 cursor-pointer" onClick={() => deleteFlashcard(flashcard.id)}/></div></li>)})}</ul></>)}
import { Action, action, createStore } from "easy-peasy";import { Flashcard } from "./types";import _db from "./data/db.json";const flashcards = _db.flashcards;export type StoreModel = {flashcards: Flashcard[];deleteFlashcard: Action<StoreModel, number>;};export const store = createStore<StoreModel>({flashcards,deleteFlashcard: action((state, payload) => {const index = state.flashcards.findIndex((m) => m.id === payload);if (index !== -1) {state.flashcards.splice(index, 1);}}),});
import { Action, action, Thunk, thunk } from "easy-peasy";import { DataFlashcard, Flashcard, ProcessStatus } from "../../types";import axios from "axios";import * as config from "../../config";export interface FlashcardModel {flashcards: Flashcard[];flashcardsLoadingStatus: ProcessStatus;// actionssetFlashcards: Action<this, Flashcard[]>;setFlashcardsLoadingStatus: Action<this, ProcessStatus>;deleteFlashcard: Action<this, Flashcard>;// thunksloadFrontendFlashcardsThunk: Thunk<this>;deleteFlashcardThunk: Thunk<this, Flashcard>;}export const flashcardModel: FlashcardModel = {flashcards: [],flashcardsLoadingStatus: "inProcess",setFlashcards: action((state, flashcards) => {state.flashcards = structuredClone(flashcards);}),setFlashcardsLoadingStatus: action((state, loadingStatus) => {state.flashcardsLoadingStatus = loadingStatus;}),deleteFlashcard: action((state, flashcard) => {const index = state.flashcards.findIndex((m) => m.dataItem.id === flashcard.dataItem.id);if (index !== -1) {state.flashcards.splice(index, 1);}}),loadFrontendFlashcardsThunk: thunk((actions) => {actions.setFlashcardsLoadingStatus("inProcess");setTimeout(async () => {try {const response = await axios.get(`http://localhost:3760/flashcards`);if (response.status === 200) {const dataFlashcards: DataFlashcard[] = response.data;const flashcards = decorateDataFlascards(dataFlashcards);actions.setFlashcards(flashcards);}actions.setFlashcardsLoadingStatus("finished");} catch (e: any) {console.log(`ERROR: ${e.message}`);actions.setFlashcardsLoadingStatus("failed");}}, config.uxLoadingSeconds() * 1000);}),deleteFlashcardThunk: thunk(async (actions, flashcard, { getState }) => {const state = getState();flashcard.deletingStatus = "inProcess";actions.setFlashcards(state.flashcards);setTimeout(async () => {try {const response = await axios.delete(`http://localhost:3760/flashcards/${flashcard.dataItem.id}`);if (response.status === 200) {console.log(`database deletion of id=${flashcard.dataItem.id} was successful`);actions.deleteFlashcard(flashcard);}} catch (e: any) {console.log(`ERROR: ${e.message}`);flashcard.deletingStatus = "failed";}}, config.uxLoadingSeconds() * 1000);}),};export const decorateDataFlascards = (dataFlashcards: DataFlashcard[]): Flashcard[] => {const flashcards: Flashcard[] = [];for (const dataFlashcard of dataFlashcards) {const flashcard: Flashcard = {dataItem: dataFlashcard,deletingStatus: "notActive",};flashcards.push(flashcard);}return flashcards;};
npm install @mui/material @emotion/react @emotion/styled
npm install @mui/icons-material
import { Button } from '@mui/material';<Button variant="contained" color="primary">Test</Button>
npm i @material-ui/core
npm install @mui/material @emotion/react @emotion/styled
(../https://mui.com/material-ui/getting-started/installation/)npm install @fontsource/roboto
import '@fontsource/roboto/300.css';import '@fontsource/roboto/400.css';import '@fontsource/roboto/500.css';import '@fontsource/roboto/700.css';
<ButtonGroup variant='contained' disableRipple><Buttonsx={{backgroundColor: 'success.main','&:hover': {backgroundColor: 'success.dark',},}}>Save</Button><Buttonsx={{backgroundColor: 'error.main','&:hover': {backgroundColor: 'error.dark',},}}>Delete</Button><Buttonsx={{backgroundColor: 'warning.main','&:hover': {backgroundColor: 'warning.dark',},}}>Copy</Button></ButtonGroup>
npm install @mui/icons-material
"@mui/icons-material": "^6.1.0","@mui/material": "^6.1.0",