Commit 31f76dda authored by Нұрасыл Қайратұлы's avatar Нұрасыл Қайратұлы

Merge branch 'update_front' into 'master'

Update front

See merge request !3
parents 66ec1700 4df12fa3
...@@ -9,11 +9,14 @@ ...@@ -9,11 +9,14 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/cors": "^2.8.17",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"save": "^2.9.0", "save": "^2.9.0",
"save-dev": "^0.0.1-security",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typescript": "^5.1.6", "typescript": "^5.1.6",
...@@ -259,6 +262,14 @@ ...@@ -259,6 +262,14 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/cors": {
"version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "4.17.17", "version": "4.17.17",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
...@@ -940,6 +951,18 @@ ...@@ -940,6 +951,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/create-require": { "node_modules/create-require": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
...@@ -2359,6 +2382,14 @@ ...@@ -2359,6 +2382,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.3", "version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
...@@ -2887,6 +2918,11 @@ ...@@ -2887,6 +2918,11 @@
"mingo": "^6.1.0" "mingo": "^6.1.0"
} }
}, },
"node_modules/save-dev": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/save-dev/-/save-dev-0.0.1-security.tgz",
"integrity": "sha512-k6knZTDNK8PKKbIqnvxiOveJinuw2LcQjqDoaorZWP9M5AR2EPsnpDeSbeoZZ0pHr5ze1uoaKdK8NBGQrJ34Uw=="
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.5.4", "version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
......
...@@ -13,11 +13,14 @@ ...@@ -13,11 +13,14 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/cors": "^2.8.17",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"save": "^2.9.0", "save": "^2.9.0",
"save-dev": "^0.0.1-security",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typescript": "^5.1.6", "typescript": "^5.1.6",
......
[
{
"id": "d2d4a838-64d2-45e1-954b-ac4d744d9497",
"title": "test",
"description": "adsdasdadadsadad",
"price": 500000
},
{
"id": "279e188c-ac70-4186-b3b1-52b9fd721e07",
"title": "asasdasd",
"description": "asdaddasad",
"price": 123123
}
]
\ No newline at end of file
...@@ -2,10 +2,11 @@ import App from './app'; ...@@ -2,10 +2,11 @@ import App from './app';
import logger from './middlewares/logger'; import logger from './middlewares/logger';
import { ArticleRoute } from './routes/article.route'; import { ArticleRoute } from './routes/article.route';
import { ProductRoute } from './routes/product.route'; import { ProductRoute } from './routes/product.route';
import cors from 'cors';
const app = new App({ const app = new App({
port: 8000, port: 8000,
middlewares: [logger()], middlewares: [logger(), cors()],
controllers: [new ArticleRoute(), new ProductRoute()], controllers: [new ArticleRoute(), new ProductRoute()],
}); });
......
...@@ -3,7 +3,7 @@ import { IRoute } from "@/interfaces/IRoute.interface"; ...@@ -3,7 +3,7 @@ import { IRoute } from "@/interfaces/IRoute.interface";
import { ProductController } from "@/controllers/product.controller"; import { ProductController } from "@/controllers/product.controller";
export class ProductRoute implements IRoute { export class ProductRoute implements IRoute {
public path = '/product'; public path = '/products';
public router = Router(); public router = Router();
private controller: ProductController; private controller: ProductController;
......
...@@ -151,6 +151,13 @@ ...@@ -151,6 +151,13 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/cors@^2.8.17":
version "2.8.17"
resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz"
integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==
dependencies:
"@types/node" "*"
"@types/express-serve-static-core@^4.17.33": "@types/express-serve-static-core@^4.17.33":
version "4.17.35" version "4.17.35"
resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz"
...@@ -560,6 +567,14 @@ cookie@0.5.0: ...@@ -560,6 +567,14 @@ cookie@0.5.0:
resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
cors@^2.8.5:
version "2.8.5"
resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
dependencies:
object-assign "^4"
vary "^1"
create-require@^1.1.0: create-require@^1.1.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz"
...@@ -1452,6 +1467,11 @@ npm-run-path@^5.1.0: ...@@ -1452,6 +1467,11 @@ npm-run-path@^5.1.0:
dependencies: dependencies:
path-key "^4.0.0" path-key "^4.0.0"
object-assign@^4:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
object-inspect@^1.9.0: object-inspect@^1.9.0:
version "1.12.3" version "1.12.3"
resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz"
...@@ -1695,6 +1715,11 @@ safe-buffer@5.2.1: ...@@ -1695,6 +1715,11 @@ safe-buffer@5.2.1:
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
save-dev@^0.0.1-security:
version "0.0.1-security"
resolved "https://registry.npmjs.org/save-dev/-/save-dev-0.0.1-security.tgz"
integrity sha512-k6knZTDNK8PKKbIqnvxiOveJinuw2LcQjqDoaorZWP9M5AR2EPsnpDeSbeoZZ0pHr5ze1uoaKdK8NBGQrJ34Uw==
save@^2.9.0: save@^2.9.0:
version "2.9.0" version "2.9.0"
resolved "https://registry.npmjs.org/save/-/save-2.9.0.tgz" resolved "https://registry.npmjs.org/save/-/save-2.9.0.tgz"
...@@ -2000,7 +2025,7 @@ validator@^13.9.0: ...@@ -2000,7 +2025,7 @@ validator@^13.9.0:
resolved "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz" resolved "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz"
integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==
vary@~1.1.2: vary@^1, vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
......
{
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"useTabs": false
}
module.exports = {
tabWidth: 2,
singleQuote: true,
trailingComma: 'es5',
printWidth: 100,
useTabs: false,
};
...@@ -10,11 +10,6 @@ ...@@ -10,11 +10,6 @@
"[typescriptreact]": { "[typescriptreact]": {
"editor.formatOnSave": true "editor.formatOnSave": true
}, },
"eslint.validate": [ "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"javascript", "typescript.tsdk": "node_modules/typescript/lib"
"javascriptreact",
"typescript",
"typescriptreact"
],
"typescript.tsdk": "node_modules/typescript/lib",
} }
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview" "preview": "vite preview",
"format": "prettier --write './**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc"
}, },
"dependencies": { "dependencies": {
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
......
const App = () => ( import { Container, CssBaseline } from '@mui/material';
import { Route, Routes } from 'react-router-dom';
import { AppToolbar } from './components/UI/AppToolbar/AppToolbar';
import { Products } from './containers/Products/Products';
import NewProduct from './containers/NewProduct/NewProduct';
function App() {
return (
<> <>
<header>Navbar will go here</header> <CssBaseline />
<main>Main content will go here</main>
<header>
<AppToolbar />
</header>
<main>
<Container maxWidth="xl" sx={{ mt: 10 }}>
<Routes>
<Route path="/" element={<Products />} />
<Route path="/products/new" element={<NewProduct />} />
</Routes>
</Container>
</main>
</> </>
); );
}
export default App; export default App;
import { useState, ChangeEvent, FormEvent } from 'react';
import { Box, Button, Grid, TextField } from '@mui/material';
import { ProductData } from '@/containers/NewProduct/NewProduct';
interface State {
title: string;
price: string;
description: string;
}
interface Props {
onSubmit: (data: ProductData) => void;
}
const ProductForm = ({onSubmit}: Props) => {
const [state, setState] = useState<State>({
title: '',
price: '',
description: '',
});
const submitFormHandler = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const newProduct: ProductData = {
title: state.title,
description: state.description,
price: parseInt(state.price),
}
onSubmit(newProduct)
};
const inputChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setState((prevState) => {
return { ...prevState, [name]: value };
});
};
return (
<Box component={'form'} autoComplete="off" onSubmit={submitFormHandler} paddingY={2}>
<Grid container direction="column" spacing={2}>
<Grid item xs>
<TextField
fullWidth
variant="outlined"
id="title"
label="Title"
value={state.title}
onChange={inputChangeHandler}
name="title"
/>
</Grid>
<Grid item xs>
<TextField
fullWidth
variant="outlined"
id="price"
label="Price"
value={state.price}
onChange={inputChangeHandler}
name="price"
/>
</Grid>
<Grid item xs>
<TextField
fullWidth
multiline
rows={3}
variant="outlined"
id="description"
label="Description"
value={state.description}
onChange={inputChangeHandler}
name="description"
/>
</Grid>
<Grid item xs>
<Button type="submit" color="primary" variant="contained">
Create
</Button>
</Grid>
</Grid>
</Box>
);
};
export default ProductForm;
import { AppBar, Box, Toolbar, Typography, styled } from '@mui/material';
import { Link } from 'react-router-dom';
const StyledLink = styled(Link)(() => ({
color: 'inherit',
textDecoration: 'none',
['&:hover']: { color: 'inherit' },
}));
export function AppToolbar() {
return (
<>
<AppBar position="fixed">
<Toolbar>
<Typography variant="h6" component={StyledLink} to={'/'}>
Computer parts shop
</Typography>
</Toolbar>
</AppBar>
<Box component={Toolbar} marginBottom={2} />
</>
);
}
import { Typography } from '@mui/material';
import ProductForm from '../../components/ProductForm/ProductForm';
import { useNavigate } from 'react-router-dom';
import { createProduct } from '../../features/productsSlice';
import { useAppDispatch } from '../../store';
export interface ProductData {
title: string;
description: string;
price: number;
}
const NewProduct = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const onProductFormSubmit = async (productData: ProductData) => {
await dispatch(createProduct(productData));
navigate('/');
};
return (
<>
<Typography variant="h4">New product</Typography>
<ProductForm onSubmit={onProductFormSubmit}/>
</>
);
};
export default NewProduct;
import { Link } from 'react-router-dom';
import {
Grid,
Card,
CardHeader,
CardContent,
CardActions,
IconButton,
Typography,
} from '@mui/material';
import { ArrowForward } from '@mui/icons-material';
import { IProduct } from '@/interfaces/IProduct';
interface Props {
product: IProduct;
}
export function ProductItem({ product }: Props) {
const { title, price, id, description } = product;
return (
<Grid item xs={12} sm={12} md={6} lg={4}>
<Card sx={{ minWidth: 275 }}>
<CardHeader title={title} />
<CardContent>
<Typography variant="body2">{description}</Typography>
<strong style={{ marginLeft: '10px' }}>Price: {price} KZT</strong>
</CardContent>
<CardActions>
<IconButton component={Link} to={`/products/${id}`}>
<ArrowForward />
</IconButton>
</CardActions>
</Card>
</Grid>
);
}
import { Link } from 'react-router-dom';
import { Typography, Grid, Button } from '@mui/material';
import { useAppDispatch, useAppSelector } from '../../store';
import { shallowEqual } from 'react-redux';
import { useEffect } from 'react';
import { fetchProducts } from '../../features/productsSlice';
import { ProductItem } from './ProductItem';
export function Products() {
const dispatch = useAppDispatch();
const { products } = useAppSelector((state) => state.products, shallowEqual);
useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
return (
<>
<Grid container direction="column" spacing={2}>
<Grid item container direction="row" justifyContent="space-between" alignItems="center">
<Grid item>
<Typography variant="h4">Products</Typography>
</Grid>
<Grid item>
<Button color="primary" component={Link} to={'/products/new'}>
Add product
</Button>
</Grid>
</Grid>
</Grid>
<Grid item container direction="row" spacing={1}>
{products.map((product) => (
<ProductItem key={product.id} product={product} />
))}
</Grid>
</>
);
}
import { createSlice } from "@reduxjs/toolkit"; import { axiosApiClient } from '../helpers/axiosApiClient';
import { IProduct } from '../interfaces/IProduct';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
const initialState = {}; interface State {
products: IProduct[];
error: Error | null;
loading: boolean;
}
const productsSlice = createSlice( const initialState: State = {
{ products: [],
error: null,
loading: false,
};
export const fetchProducts = createAsyncThunk('fetch/products', async () => {
return await axiosApiClient.get<IProduct[]>('/products').then((res) => res.data);
});
export const createProduct = createAsyncThunk('create/products', async (payload: IProduct) => {
return await axiosApiClient.post<IProduct>('/products', payload).then((res) => res.data);
});
const productsSlice = createSlice({
name: 'products', name: 'products',
initialState, initialState,
reducers: {}, reducers: {},
} extraReducers: (builder) => {
) builder
.addCase(fetchProducts.fulfilled, (state, action) => {
state.products = action.payload;
state.loading = false;
})
.addCase(fetchProducts.rejected, (state, action) => {
state.error = action.error as Error;
state.loading = false;
})
.addCase(fetchProducts.pending, (state) => {
state.loading = true;
});
},
});
export default productsSlice.reducer; export default productsSlice.reducer;
import axios from 'axios';
export const axiosApiClient = axios.create({
baseURL: 'http://localhost:8000',
});
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
code { code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
monospace;
} }
export interface IProduct {
id?: string;
title: string;
description: string;
price: number;
}
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import productsReducer from '../features/productsSlice.ts'; import productsReducer from '../features/productsSlice.ts';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
const store = configureStore({ const store = configureStore({
reducer: { reducer: {
products: productsReducer, products: productsReducer,
} },
}) });
type RootState = ReturnType<typeof store.getState>;
type AppDispatch = typeof store.dispatch;
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export default store; export default store;
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES2020",
"useDefineForClassFields": true, "useDefineForClassFields": true,
"lib": [ "lib": ["ES2020", "DOM", "DOM.Iterable"],
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext", "module": "ESNext",
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */
...@@ -22,14 +18,10 @@ ...@@ -22,14 +18,10 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"paths": { "paths": {
"@/*": [ "@/*": ["./src/*"]
"./src/*"
]
} }
}, },
"include": [ "include": ["src"],
"src"
],
"references": [ "references": [
{ {
"path": "./tsconfig.node.json" "path": "./tsconfig.node.json"
......
import { defineConfig } from 'vite' import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc' import react from '@vitejs/plugin-react-swc';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
}) });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment