Added most of backend interactions and rewrote filers logic
This commit is contained in:
parent
a83e667dae
commit
403c57cdba
104
src/App.tsx
104
src/App.tsx
@ -1,62 +1,98 @@
|
||||
import React, { useState } from "react";
|
||||
import { Switch, Route, useLocation } from "react-router-dom";
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Switch, Route, useHistory } from 'react-router-dom';
|
||||
|
||||
import "./App.css";
|
||||
import Home from "./Home";
|
||||
import Navbar from "./Navbar";
|
||||
import SubjectList from "./SubjectList";
|
||||
import {ILoadingState} from './types'
|
||||
import './App.css';
|
||||
import Home from './Home';
|
||||
import Navbar from './Navbar';
|
||||
import { queryIsEmpty } from './Navbar/utils';
|
||||
import SubjectList from './SubjectList';
|
||||
import { ILoadingState, IFilterQuery } from './types';
|
||||
|
||||
const genName = (path: string, search?: string): string => {
|
||||
if (path === "/list" && search) {
|
||||
search = decodeURI(search);
|
||||
let query: any = {};
|
||||
search
|
||||
.split("?")
|
||||
.slice(1)
|
||||
.map((param) => (query[param.split("=")[0]] = param.split("=")[1]));
|
||||
const genName = (searchQuery: IFilterQuery, path: string): string => {
|
||||
if (path === '/list' && searchQuery) {
|
||||
let result = '';
|
||||
|
||||
let result = "";
|
||||
|
||||
if (query.clas) {
|
||||
result = result + query.clas + " класс";
|
||||
if (searchQuery.class_num) {
|
||||
result = result + searchQuery.class_num + ' класс';
|
||||
}
|
||||
|
||||
if (query.subject) {
|
||||
result = result + ", " + query.subject;
|
||||
if (searchQuery.predmet_type) {
|
||||
result = result + ' ' + searchQuery.predmet_type;
|
||||
}
|
||||
|
||||
if (query.teacher) {
|
||||
result = result + ", " + query.teacher;
|
||||
if (searchQuery.teacher) {
|
||||
result = result + ' ' + searchQuery.teacher;
|
||||
}
|
||||
|
||||
if (searchQuery.search) {
|
||||
result = result + ' поиск по "' + searchQuery.search + '"';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (path === "/") {
|
||||
return "Банк семинаров";
|
||||
if (path === '/') {
|
||||
return 'Банк семинаров';
|
||||
}
|
||||
|
||||
return "";
|
||||
return '';
|
||||
};
|
||||
|
||||
function App() {
|
||||
const location = useLocation();
|
||||
const useDidUpdate: typeof useEffect = (func, dependencies) => {
|
||||
const didMountRef = useRef(false);
|
||||
|
||||
const [loading, setLoading] = useState<ILoadingState>({ fetching: true, error: "" });
|
||||
useEffect(() => {
|
||||
if (didMountRef.current) {
|
||||
func();
|
||||
} else {
|
||||
didMountRef.current = true;
|
||||
}
|
||||
|
||||
return () => {};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, dependencies);
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
const history = useHistory();
|
||||
|
||||
const [loading, setLoading] = useState<ILoadingState>({
|
||||
fetching: true,
|
||||
error: ''
|
||||
});
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState<IFilterQuery>({
|
||||
search: '',
|
||||
class_num: '',
|
||||
type_num: '',
|
||||
predmet_type: '',
|
||||
teacher: ''
|
||||
});
|
||||
|
||||
useDidUpdate(() => {
|
||||
if (queryIsEmpty(searchQuery)) return;
|
||||
|
||||
history.push('/list');
|
||||
}, [searchQuery]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<header id="name">
|
||||
<h1>{genName(location.pathname, location.search)}</h1>
|
||||
<h1>{genName(searchQuery, history.location.pathname)}</h1>
|
||||
</header>
|
||||
<Navbar />
|
||||
<Navbar query={searchQuery} setSearchQuery={setSearchQuery} />
|
||||
<Switch>
|
||||
<Route exact path="/">
|
||||
<Home setLoading={setLoading} />
|
||||
<Home
|
||||
setLoading={setLoading}
|
||||
setSearchQuery={setSearchQuery}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/list">
|
||||
<SubjectList setLoading={setLoading} />
|
||||
<SubjectList
|
||||
searchQuery={searchQuery}
|
||||
setLoading={setLoading}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<h1>404</h1>
|
||||
@ -64,6 +100,6 @@ function App() {
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
@ -1,12 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
import './main.css'
|
||||
|
||||
const Card = (props) => (
|
||||
<a className="card" href={ '/' + props.data.image.slice(props.data.image.indexOf('media'))}>
|
||||
<h4 className="cardTitle">{props.data.title}</h4>
|
||||
<h5 className="cardTeacher">{props.data.teacher}</h5>
|
||||
</a>
|
||||
);
|
||||
|
||||
export default Card;
|
16
src/Card/index.tsx
Normal file
16
src/Card/index.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { IData } from '../types';
|
||||
|
||||
import './main.css';
|
||||
|
||||
const Card = ({ data }: { data: IData }) => (
|
||||
<a
|
||||
className="card"
|
||||
href={'/' + data.image.slice(data.image.indexOf('media'))}
|
||||
>
|
||||
<h4 className="cardTitle">{data.title}</h4>
|
||||
<h5 className="cardTeacher">{data.teacher}</h5>
|
||||
</a>
|
||||
);
|
||||
|
||||
export default Card;
|
@ -1,27 +1,28 @@
|
||||
import React, { Dispatch, useEffect, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Card from "../Card";
|
||||
import { IData, ILoadingState } from "../types";
|
||||
import "./main.css";
|
||||
import Card from '../Card';
|
||||
import { IData, IFilterQuery, ILoadingState } from '../types';
|
||||
import './main.css';
|
||||
|
||||
const Home = ({ setLoading }: {setLoading: Dispatch<ILoadingState>}) => {
|
||||
const Home = ({
|
||||
setLoading,
|
||||
setSearchQuery
|
||||
}: {
|
||||
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
||||
setSearchQuery: Dispatch<SetStateAction<IFilterQuery>>;
|
||||
}) => {
|
||||
const [data, setData] = useState<IData[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading({ fetching: true, error: "" });
|
||||
console.log("Loading data");
|
||||
setLoading({ fetching: true, error: '' });
|
||||
|
||||
const requestURL =
|
||||
"https://cors-anywhere.herokuapp.com/upml-bank.dmitriy.icu/api/cards";
|
||||
const requestURL = 'https://upml-bank.dmitriy.icu/api/cards';
|
||||
fetch(requestURL)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log("Fetched data");
|
||||
console.log(data);
|
||||
|
||||
setData(data);
|
||||
setLoading({ fetching: false, error: "" });
|
||||
setLoading({ fetching: false, error: '' });
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading({ fetching: false, error: err });
|
||||
@ -30,9 +31,17 @@ const Home = ({ setLoading }: {setLoading: Dispatch<ILoadingState>}) => {
|
||||
}, [setLoading]);
|
||||
|
||||
const classes: number[] = [
|
||||
...Array.from(new Set(data.map((el) => parseInt(el.class_num)).sort())),
|
||||
...Array.from(new Set(data.map((el) => parseInt(el.class_num)).sort()))
|
||||
];
|
||||
const subjects: string[] = [...Array.from(new Set(data.map((el) => el.predmet_type).sort()))];
|
||||
const subjects: string[] = [
|
||||
...Array.from(new Set(data.map((el) => el.predmet_type).sort()))
|
||||
];
|
||||
|
||||
const handleShowMore = (predmet_type: string, class_num: number) => {
|
||||
setSearchQuery((prev): IFilterQuery => {
|
||||
return { ...prev, predmet_type, class_num: class_num.toString() };
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="homeContainer">
|
||||
@ -62,12 +71,13 @@ const Home = ({ setLoading }: {setLoading: Dispatch<ILoadingState>}) => {
|
||||
</div>
|
||||
<div className="showMore">
|
||||
<Link
|
||||
to={
|
||||
"/list?subject=" +
|
||||
subject +
|
||||
"?clas=" +
|
||||
class_num
|
||||
onClick={() =>
|
||||
handleShowMore(
|
||||
subject,
|
||||
class_num
|
||||
)
|
||||
}
|
||||
to={'/list'}
|
||||
>
|
||||
Больше →
|
||||
</Link>
|
||||
@ -75,7 +85,7 @@ const Home = ({ setLoading }: {setLoading: Dispatch<ILoadingState>}) => {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
''
|
||||
)
|
||||
)}
|
||||
|
||||
|
@ -1,57 +1,138 @@
|
||||
import React, { useState } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Link } from "react-router-dom";
|
||||
import React, {
|
||||
ChangeEvent,
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import "./main.css";
|
||||
import './main.css';
|
||||
|
||||
import LogoImage from "./logo.png";
|
||||
import FilterIcon from "./filter.svg";
|
||||
import SearchIcon from "./search.svg";
|
||||
import LogoImage from './logo.png';
|
||||
import FilterIcon from './filter.svg';
|
||||
import SearchIcon from './search.svg';
|
||||
import { IFilterQuery } from '../types';
|
||||
import { emptyQuery } from './utils';
|
||||
import { useFocus } from '../utils';
|
||||
|
||||
const Navbar = ({
|
||||
setSearchQuery,
|
||||
query
|
||||
}: {
|
||||
setSearchQuery: Dispatch<SetStateAction<IFilterQuery>>;
|
||||
query: IFilterQuery;
|
||||
}) => {
|
||||
/*
|
||||
* Hooks
|
||||
*/
|
||||
|
||||
const Navbar = () => {
|
||||
const [searchCollapsed, setSearchCollapsed] = useState(true);
|
||||
const [filtersCollapsed, setFiltersCollapsed] = useState(true);
|
||||
const [localFilters, setLocalFilters] = useState<Partial<IFilterQuery>>();
|
||||
|
||||
const searchInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
const setInputFocus = useFocus(searchInput);
|
||||
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (formRef.current) {
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
console.log(key, value);
|
||||
if (formRef.current.elements.namedItem(key)) {
|
||||
(formRef.current.elements.namedItem(
|
||||
key
|
||||
) as HTMLSelectElement).value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [query]);
|
||||
|
||||
/*
|
||||
* Animations
|
||||
*/
|
||||
|
||||
const searchVariants = {
|
||||
open: {
|
||||
width: "calc(100vw - 4vh)",
|
||||
display: "block",
|
||||
width: 'calc(100vw - 4vh)',
|
||||
display: 'block'
|
||||
},
|
||||
closed: {
|
||||
width: "6vh",
|
||||
width: '6vh',
|
||||
transitionEnd: {
|
||||
display: "none",
|
||||
},
|
||||
},
|
||||
display: 'none'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navVariants = {
|
||||
open: {
|
||||
height: "100vh",
|
||||
height: '100vh',
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopRightRadius: 0,
|
||||
borderTopRightRadius: 0
|
||||
},
|
||||
closed: {
|
||||
height: "10vh",
|
||||
borderTopLeftRadius: "20px",
|
||||
borderTopRightRadius: "20px",
|
||||
},
|
||||
height: '10vh',
|
||||
borderTopLeftRadius: '20px',
|
||||
borderTopRightRadius: '20px'
|
||||
}
|
||||
};
|
||||
|
||||
const filtersVariants = {
|
||||
open: {
|
||||
height: "100vh",
|
||||
padding: "2vh",
|
||||
height: '100vh',
|
||||
padding: '2vh'
|
||||
},
|
||||
closed: {
|
||||
height: 0,
|
||||
padding: 0,
|
||||
},
|
||||
padding: 0
|
||||
}
|
||||
};
|
||||
|
||||
const transition = {
|
||||
ease: "easeIn",
|
||||
duration: 0.5,
|
||||
ease: 'easeIn',
|
||||
duration: 0.5
|
||||
};
|
||||
|
||||
/*
|
||||
* Input handlers
|
||||
*/
|
||||
|
||||
const handleFiltersButton = () => {
|
||||
if (!filtersCollapsed) {
|
||||
setSearchQuery((prev) => {
|
||||
return { ...prev, ...localFilters };
|
||||
});
|
||||
}
|
||||
setFiltersCollapsed((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleSelectChange = ({
|
||||
target: element
|
||||
}: ChangeEvent<HTMLSelectElement>) => {
|
||||
setLocalFilters((prev) => {
|
||||
return { ...prev, [element.name]: element.value };
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearchButton = () => {
|
||||
if (searchCollapsed) {
|
||||
setSearchCollapsed(false);
|
||||
setInputFocus();
|
||||
} else if (searchInput && searchInput.current) {
|
||||
const value = searchInput.current.value;
|
||||
|
||||
setSearchQuery((prev) => {
|
||||
return { ...prev, search: value };
|
||||
});
|
||||
setSearchCollapsed(true);
|
||||
|
||||
searchInput.current.value = '';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@ -59,10 +140,15 @@ const Navbar = () => {
|
||||
id="navbar"
|
||||
variants={navVariants}
|
||||
transition={transition}
|
||||
animate={filtersCollapsed ? "closed" : "open"}
|
||||
animate={filtersCollapsed ? 'closed' : 'open'}
|
||||
>
|
||||
<nav>
|
||||
<Link to="/">
|
||||
<Link
|
||||
to="/"
|
||||
onClick={() => {
|
||||
emptyQuery(setSearchQuery);
|
||||
}}
|
||||
>
|
||||
<img id="logo" src={LogoImage} alt="Логотип ЮФМЛ" />
|
||||
</Link>
|
||||
|
||||
@ -71,7 +157,7 @@ const Navbar = () => {
|
||||
<button
|
||||
className="navButton"
|
||||
id="filter"
|
||||
onClick={() => setFiltersCollapsed((prev) => !prev)}
|
||||
onClick={handleFiltersButton}
|
||||
>
|
||||
<img src={FilterIcon} alt="Фильтр" />
|
||||
</button>
|
||||
@ -79,16 +165,17 @@ const Navbar = () => {
|
||||
<button
|
||||
className="navButton"
|
||||
id="search"
|
||||
onClick={() => setSearchCollapsed((prev) => !prev)}
|
||||
onClick={handleSearchButton}
|
||||
>
|
||||
<img src={SearchIcon} alt="Поиск" />
|
||||
</button>
|
||||
<motion.input
|
||||
type="search"
|
||||
animate={searchCollapsed ? "closed" : "open"}
|
||||
animate={searchCollapsed ? 'closed' : 'open'}
|
||||
variants={searchVariants}
|
||||
transition={transition}
|
||||
aria-label="Поиск"
|
||||
ref={searchInput}
|
||||
type="search"
|
||||
name="search"
|
||||
id="searchInput"
|
||||
/>
|
||||
@ -97,17 +184,20 @@ const Navbar = () => {
|
||||
<motion.form
|
||||
variants={filtersVariants}
|
||||
transition={transition}
|
||||
animate={filtersCollapsed ? "closed" : "open"}
|
||||
animate={filtersCollapsed ? 'closed' : 'open'}
|
||||
id="filters"
|
||||
ref={formRef}
|
||||
>
|
||||
<div>
|
||||
<label htmlFor="teacherFilter">
|
||||
<h2>Преподаватель</h2>
|
||||
</label>
|
||||
<select name="teacher" id="teacherFilter">
|
||||
<option value="">
|
||||
-
|
||||
</option>
|
||||
<select
|
||||
name="teacher"
|
||||
onChange={handleSelectChange}
|
||||
id="teacherFilter"
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="Попов Д.А">Попов Д.А</option>
|
||||
<option value="Ильин А.Б">Ильин А.Б</option>
|
||||
<option value="Пачин И.М">Пачин И.М</option>
|
||||
@ -127,10 +217,12 @@ const Navbar = () => {
|
||||
<label htmlFor="typeFilter">
|
||||
<h2>Тип задания</h2>
|
||||
</label>
|
||||
<select name="type_num" id="typeFilter">
|
||||
<option value="">
|
||||
-
|
||||
</option>
|
||||
<select
|
||||
name="type_num"
|
||||
onChange={handleSelectChange}
|
||||
id="typeFilter"
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="Семестровки">Семестровки</option>
|
||||
<option value="Семинары">Семинары</option>
|
||||
<option value="Потоковые">Потоковые</option>
|
||||
@ -140,10 +232,12 @@ const Navbar = () => {
|
||||
<label htmlFor="predmetFilter">
|
||||
<h2>Предмет</h2>
|
||||
</label>
|
||||
<select name="predmet_type" id="predmetFilter">
|
||||
<option value="">
|
||||
-
|
||||
</option>
|
||||
<select
|
||||
name="predmet_type"
|
||||
onChange={handleSelectChange}
|
||||
id="predmetFilter"
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="Математика">Математика</option>
|
||||
<option value="Физика">Физика</option>
|
||||
<option value="Информатика">Информатика</option>
|
||||
@ -153,10 +247,12 @@ const Navbar = () => {
|
||||
<label htmlFor="classFilter">
|
||||
<h2>Класс</h2>
|
||||
</label>
|
||||
<select name="class_num" id="classFilter">
|
||||
<option value="">
|
||||
-
|
||||
</option>
|
||||
<select
|
||||
name="class_num"
|
||||
onChange={handleSelectChange}
|
||||
id="classFilter"
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
</select>
|
||||
|
24
src/Navbar/utils.ts
Normal file
24
src/Navbar/utils.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { IFilterQuery } from '../types';
|
||||
|
||||
const queryIsEmpty = (q: IFilterQuery): boolean => {
|
||||
for (const [_, value] of Object.entries(q)) {
|
||||
if (value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const emptyQuery = (setter: Dispatch<SetStateAction<IFilterQuery>>) => {
|
||||
setter({
|
||||
class_num: '',
|
||||
type_num: '',
|
||||
predmet_type: '',
|
||||
search: '',
|
||||
teacher: ''
|
||||
});
|
||||
};
|
||||
|
||||
export { queryIsEmpty, emptyQuery };
|
@ -1,20 +1,32 @@
|
||||
import React, { useEffect, useState, Dispatch } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { IData, ILoadingState } from '../types';
|
||||
import { IData, ILoadingState, IFilterQuery } from '../types';
|
||||
import { queryIsEmpty } from '../Navbar/utils';
|
||||
import Card from '../Card';
|
||||
import './main.css';
|
||||
|
||||
const SubjectList = ({
|
||||
setLoading
|
||||
setLoading,
|
||||
searchQuery
|
||||
}: {
|
||||
setLoading: Dispatch<ILoadingState>;
|
||||
searchQuery: IFilterQuery;
|
||||
}) => {
|
||||
const [data, setData] = useState<IData[]>([]);
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
if (queryIsEmpty(searchQuery)) {
|
||||
history.push('/');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading({ fetching: true, error: '' });
|
||||
const fetchURL = 'https://upml-bank.dmitriy.icu/api/cards?' + new URLSearchParams({class_num: '11'}).toString()
|
||||
const fetchURL =
|
||||
'https://upml-bank.dmitriy.icu/api/cards?' +
|
||||
new URLSearchParams({ ...searchQuery }).toString();
|
||||
fetch(fetchURL)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
@ -25,7 +37,7 @@ const SubjectList = ({
|
||||
console.error(err);
|
||||
setLoading({ fetching: false, error: err });
|
||||
});
|
||||
}, [setLoading]);
|
||||
}, [setLoading, searchQuery]);
|
||||
|
||||
return (
|
||||
<main className="subjectList">
|
||||
|
@ -4,6 +4,7 @@
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
@ -36,4 +37,7 @@ code {
|
||||
#name h1 {
|
||||
text-align: center;
|
||||
line-height: 6vh;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
10
src/types.ts
10
src/types.ts
@ -15,4 +15,12 @@ interface IData {
|
||||
card_id: number;
|
||||
}
|
||||
|
||||
export type { ILoadingState, IData };
|
||||
interface IFilterQuery {
|
||||
class_num: string;
|
||||
type_num: string;
|
||||
predmet_type: string;
|
||||
teacher: string;
|
||||
search: string;
|
||||
}
|
||||
|
||||
export type { ILoadingState, IData, IFilterQuery };
|
||||
|
11
src/utils.ts
Normal file
11
src/utils.ts
Normal file
@ -0,0 +1,11 @@
|
||||
const useFocus = (focusRef: React.RefObject<HTMLInputElement>) => {
|
||||
const setFocus = () => {
|
||||
setTimeout(() => {
|
||||
focusRef.current && focusRef.current.focus();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
return setFocus;
|
||||
};
|
||||
|
||||
export { useFocus };
|
@ -1,25 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react",
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user