lint everything

This commit is contained in:
2023-11-18 16:34:09 +01:00
parent 68e5977fb2
commit 1af65eb479
78 changed files with 2282 additions and 2258 deletions

View File

@@ -1,9 +1,6 @@
// @ts-check
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
fixable: 'code',
},
create(context) {
return {
ImportDeclaration(node) {
@@ -12,15 +9,18 @@ module.exports = {
node.source.value === '@reduxjs/toolkit/query'
) {
context.report({
node,
message:
"Import from '@reduxjs/toolkit/query/' is disallowed. Please import from '@reduxjs/toolkit/query/react'.",
fix(fixer) {
return fixer.replaceText(node.source, "'@reduxjs/toolkit/query/react'")
},
message:
"Import from '@reduxjs/toolkit/query/' is disallowed. Please import from '@reduxjs/toolkit/query/react'.",
node,
})
}
},
}
},
meta: {
fixable: 'code',
},
}

View File

@@ -8,7 +8,8 @@
"build": "tsc && vite build",
"preview": "vite preview",
"format": "prettier --write src",
"lint": "eslint --fix src/**/*.{tsx,ts,jsx,js} --no-error-on-unmatched-pattern && stylelint --fix src/{,*/}*.{scss,css} --allow-empty-input",
"lint": "eslint . --ext .jsx,.js,.tsx,.ts --no-error-on-unmatched-pattern --fix && stylelint --fix src/{,*/}*.{scss,css} --allow-empty-input",
"sb": "storybook dev -p 6006",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},

View File

@@ -1,17 +1,17 @@
export { default as Eye } from './eye'
export { default as VisibilityOff } from './visibility-off'
export { default as Check } from './check'
export { default as Email } from './email'
export { default as Camera } from './camera'
export { default as Logout } from './logout'
export { default as Edit } from './edit'
export { default as Logo } from './logo'
export { default as PersonOutline } from './person-outline'
export { default as Check } from './check'
export { default as ChevronUp } from './chevron-up'
export { default as Close } from './close'
export { default as Search } from './search'
export { default as Edit } from './edit'
export { default as Edit2Outline } from './edit-2-outline'
export { default as Email } from './email'
export { default as Eye } from './eye'
export { default as KeyboardArrowLeft } from './keyboard-arrow-left'
export { default as KeyboardArrowRight } from './keyboard-arrow-right'
export { default as Logo } from './logo'
export { default as Logout } from './logout'
export { default as PersonOutline } from './person-outline'
export { default as PlayCircleOutline } from './play-circle-outline'
export { default as Edit2Outline } from './edit-2-outline'
export { default as Search } from './search'
export { default as TrashOutline } from './trash-outline'
export { default as VisibilityOff } from './visibility-off'

View File

@@ -11,7 +11,9 @@ const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) =
>
<g clipPath={'url(#clip0_5928_3055)'}>
<path
d={'M10.2733 11.06L7.21998 8L10.2733 4.94L9.33331 4L5.33331 8L9.33331 12L10.2733 11.06Z'}
d={
'M10.2733 11.06L7.21998 8L10.2733 4.94L9.33331 4L5.33331 8L9.33331 12L10.2733 11.06Z'
}
fill={'white'}
/>
</g>

View File

@@ -11,7 +11,9 @@ const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) =
>
<g clipPath={'url(#clip0_5928_3027)'}>
<path
d={'M5.72665 11.06L8.77999 8L5.72665 4.94L6.66665 4L10.6667 8L6.66665 12L5.72665 11.06Z'}
d={
'M5.72665 11.06L8.77999 8L5.72665 4.94L6.66665 4L10.6667 8L6.66665 12L5.72665 11.06Z'
}
fill={'white'}
/>
</g>

View File

@@ -1,35 +1,21 @@
import { Ref, SVGProps, forwardRef, memo } from 'react'
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
import { SVGProps, Ref, forwardRef, memo } from "react"
const SvgComponent = (
props: SVGProps<SVGSVGElement>,
ref: Ref<SVGSVGElement>
) => (
<svg
fill={'none'}
height={'16'}
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
fill="none"
ref={ref}
viewBox={'0 0 16 16'}
width={'16'}
xmlns={'http://www.w3.org/2000/svg'}
{...props}
>
<g clipPath={'url(#clip0_6627_107)'}>
<path
d={
'M4.66663 3.99996C4.84344 3.99996 5.01301 3.92972 5.13803 3.8047C5.26305 3.67967 5.33329 3.5101 5.33329 3.33329C5.33329 3.15648 5.26305 2.98691 5.13803 2.86189C5.01301 2.73686 4.84344 2.66663 4.66663 2.66663H3.33329C3.15648 2.66663 2.98691 2.73686 2.86189 2.86189C2.73686 2.98691 2.66663 3.15648 2.66663 3.33329V12.6666C2.66663 12.8434 2.73686 13.013 2.86189 13.138C2.98691 13.2631 3.15648 13.3333 3.33329 13.3333H4.66663C4.84344 13.3333 5.01301 13.2631 5.13803 13.138C5.26305 13.013 5.33329 12.8434 5.33329 12.6666C5.33329 12.4898 5.26305 12.3202 5.13803 12.1952C5.01301 12.0702 4.84344 12 4.66663 12H3.99996V3.99996H4.66663Z'
}
fill={'white'}
/>
<path
d={
'M13.88 7.61338L12 4.94672C11.898 4.80299 11.7433 4.70548 11.5697 4.67549C11.396 4.64551 11.2176 4.6855 11.0733 4.78672C11.0012 4.83724 10.9399 4.90154 10.8927 4.97592C10.8456 5.05029 10.8137 5.13326 10.7988 5.22004C10.784 5.30681 10.7864 5.39568 10.8061 5.4815C10.8257 5.56732 10.8622 5.64839 10.9133 5.72005L12.06 7.33338H6.66667C6.48986 7.33338 6.32029 7.40362 6.19526 7.52864C6.07024 7.65367 6 7.82324 6 8.00005C6 8.17686 6.07024 8.34643 6.19526 8.47145C6.32029 8.59648 6.48986 8.66672 6.66667 8.66672H12L10.8 10.2667C10.7475 10.3368 10.7093 10.4165 10.6875 10.5013C10.6658 10.5861 10.661 10.6743 10.6734 10.761C10.6857 10.8477 10.7151 10.931 10.7597 11.0064C10.8043 11.0817 10.8633 11.1475 10.9333 11.2C11.0487 11.2866 11.1891 11.3334 11.3333 11.3334C11.4368 11.3334 11.5389 11.3093 11.6315 11.263C11.724 11.2167 11.8046 11.1495 11.8667 11.0667L13.8667 8.40005C13.952 8.28729 13.9994 8.15031 14.0018 8.00889C14.0041 7.86748 13.9615 7.72897 13.88 7.61338Z'
}
fill={'white'}
/>
<g fill="#000" clipPath="url(#a)">
<path d="M7 6a1 1 0 0 0 0-2H5a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h2a1 1 0 0 0 0-2H6V6h1Zm13.82 5.42-2.82-4a1 1 0 1 0-1.63 1.16L18.09 11H10a1 1 0 0 0 0 2h8l-1.8 2.4a1 1 0 0 0 1.6 1.2l3-4a1 1 0 0 0 .02-1.18Z" />
</g>
<defs>
<clipPath id={'clip0_6627_107'}>
<rect fill={'white'} height={'16'} width={'16'} />
</clipPath>
</defs>
</svg>
)
const ForwardRef = forwardRef(SvgComponent)
export default memo(ForwardRef)
const Memo = memo(ForwardRef)
export default Memo

View File

@@ -38,7 +38,11 @@ export const RecoverPassword = (props: Props) => {
</Typography>
<form onSubmit={handleFormSubmitted}>
<div className={s.form}>
<ControlledTextField control={control} name={'email'} placeholder={'Email'} />
<ControlledTextField
control={control}
name={'email'}
placeholder={'Email'}
/>
</div>
<Typography className={s.instructions} variant={'body2'}>
Enter your email address and we will send you further instructions

View File

@@ -38,7 +38,12 @@ export const DeckDialog = ({
}
return (
<Dialog {...dialogProps} onCancel={handleCancel} onConfirm={onSubmit} title={'Create new deck'}>
<Dialog
{...dialogProps}
onCancel={handleCancel}
onConfirm={onSubmit}
title={'Create new deck'}
>
<form className={s.content} onSubmit={onSubmit}>
<ControlledTextField control={control} label={'Deck name'} name={'name'} />
<ControlledCheckbox

View File

@@ -72,7 +72,10 @@ export const DecksTable = ({ currentUserId, decks, onDeleteClick, onEditClick }:
<Button onClick={handleEditClick(deck.id)} variant={'icon'}>
<Edit2Outline />
</Button>
<Button onClick={handleDeleteClick(deck.id)} variant={'icon'}>
<Button
onClick={handleDeleteClick(deck.id)}
variant={'icon'}
>
<TrashOutline />
</Button>
</>

View File

@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './'
import {Camera} from "@/assets";
const meta = {
argTypes: {
@@ -19,7 +20,7 @@ type Story = StoryObj<typeof meta>
export const Primary: Story = {
args: {
children: 'Primary Button',
children: <>Turn Camera On <Camera/></>,
disabled: false,
variant: 'primary',
},
@@ -58,8 +59,9 @@ export const FullWidth: Story = {
export const AsLink: Story = {
args: {
as: 'a',
as: 'button',
children: 'Link that looks like a button',
variant: 'primary',
href: 'https://google.com',
},
}

View File

@@ -14,6 +14,9 @@ export const Button = <T extends ElementType = 'button'>(props: ButtonProps<T>)
const { as: Component = 'button', className, fullWidth, variant = 'primary', ...rest } = props
return (
<Component className={`${s[variant]} ${fullWidth ? s.fullWidth : ''} ${className}`} {...rest} />
<Component
className={`${s[variant]} ${fullWidth ? s.fullWidth : ''} ${className}`}
{...rest}
/>
)
}

View File

@@ -51,7 +51,10 @@ export const Checkbox: FC<CheckboxProps> = ({
required={required}
>
{checked && (
<CheckboxRadix.Indicator className={classNames.indicator} forceMount>
<CheckboxRadix.Indicator
className={classNames.indicator}
forceMount
>
<Check />
</CheckboxRadix.Indicator>
)}

View File

@@ -153,7 +153,14 @@ const MainPaginationButtons: FC<MainPaginationButtonsProps> = ({
return <Dots key={index} />
}
return <PageButton key={index} onClick={onClick(page)} page={page} selected={isSelected} />
return (
<PageButton
key={index}
onClick={onClick(page)}
page={page}
selected={isSelected}
/>
)
})}
</>
)

View File

@@ -3,7 +3,7 @@ import { useCallback, useMemo } from 'react'
// original code: https://www.freecodecamp.org/news/build-a-custom-pagination-component-in-react/
const range = (start: number, end: number) => {
let length = end - start + 1
const length = end - start + 1
/*
Create an array of certain length and set the elements within it from
@@ -16,14 +16,14 @@ const DOTS = '...'
type UsePaginationParamType = {
count: number
siblings?: number
page: number
onChange: (pageNumber: number) => void
page: number
siblings?: number
}
type PaginationRange = (number | '...')[]
type PaginationRange = ('...' | number)[]
export const usePagination = ({ count, siblings = 1, page, onChange }: UsePaginationParamType) => {
export const usePagination = ({ count, onChange, page, siblings = 1 }: UsePaginationParamType) => {
const paginationRange = useMemo(() => {
// Pages count is determined as siblingCount + firstPage + lastPage + page + 2*DOTS
const totalPageNumbers = siblings + 5
@@ -58,8 +58,8 @@ export const usePagination = ({ count, siblings = 1, page, onChange }: UsePagina
Case 2: No left dots to show, but rights dots to be shown
*/
if (!shouldShowLeftDots && shouldShowRightDots) {
let leftItemCount = 3 + 2 * siblings
let leftRange = range(1, leftItemCount)
const leftItemCount = 3 + 2 * siblings
const leftRange = range(1, leftItemCount)
return [...leftRange, DOTS, count]
}
@@ -68,8 +68,8 @@ export const usePagination = ({ count, siblings = 1, page, onChange }: UsePagina
Case 3: No right dots to show, but left dots to be shown
*/
if (shouldShowLeftDots && !shouldShowRightDots) {
let rightItemCount = 3 + 2 * siblings
let rightRange = range(count - rightItemCount + 1, count)
const rightItemCount = 3 + 2 * siblings
const rightRange = range(count - rightItemCount + 1, count)
return [firstPageIndex, DOTS, ...rightRange]
}
@@ -78,7 +78,7 @@ export const usePagination = ({ count, siblings = 1, page, onChange }: UsePagina
Case 4: Both left and right dots to be shown
*/
if (shouldShowLeftDots && shouldShowRightDots) {
let middleRange = range(leftSiblingIndex, rightSiblingIndex)
const middleRange = range(leftSiblingIndex, rightSiblingIndex)
return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex]
}
@@ -102,11 +102,11 @@ export const usePagination = ({ count, siblings = 1, page, onChange }: UsePagina
}
return {
paginationRange,
isFirstPage,
isLastPage,
handleMainPageClicked,
handleNextPageClicked,
handlePreviousPageClicked,
isFirstPage,
isLastPage,
paginationRange,
}
}

View File

@@ -25,9 +25,9 @@ export const Default = {
<TableRow>
<TableCell>Web Basic</TableCell>
<TableCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut sed do eiusmod tempoei usmodr sit amet, consectetur adipiscing elit, sed
do...
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut sed do eiusmod tempoei usmodr sit amet, consectetur
adipiscing elit, sed do...
</TableCell>
<TableCell>
<Typography
@@ -36,8 +36,8 @@ export const Default = {
target={'_blank'}
variant={'link1'}
>
Какая-то ссылка кудато на какой-то источник с информациейо ссылка кудато на какой-то
источник
Какая-то ссылка кудато на какой-то источник с информациейо ссылка
кудато на какой-то источник
</Typography>
</TableCell>
<TableCell>Основной</TableCell>
@@ -47,13 +47,13 @@ export const Default = {
<TableRow>
<TableCell>Web Basic</TableCell>
<TableCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut sed do eiusmod tempoei usmodr sit amet, consectetur adipiscing elit, sed
do...
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut sed do eiusmod tempoei usmodr sit amet, consectetur
adipiscing elit, sed do...
</TableCell>
<TableCell>
Какая-то ссылка кудато на какой-то источник с информациейо ссылка кудато на какой-то
источник
Какая-то ссылка кудато на какой-то источник с информациейо ссылка кудато
на какой-то источник
</TableCell>
<TableCell>Основной</TableCell>
<TableCell>Читать</TableCell>
@@ -68,7 +68,8 @@ export const Default = {
const data = [
{
category: 'Основной',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
id: '01',
link: 'Какая-то ссылка кудато на какой-то источник с информациейо ссылка кудато на какой-то',
title: 'Web Basic',
@@ -76,7 +77,8 @@ const data = [
},
{
category: 'Основной',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
id: '02',
link: 'Какая-то ссылка куда-то',
title: 'Web Basic',
@@ -84,7 +86,8 @@ const data = [
},
{
category: 'Основной',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor',
id: '03',
link: 'Какая-то ссылка кудато на какой-то источник с информациейо ссылка кудато на какой-то. Какая-то ссылка кудато на какой-то источник с информациейо ссылка куда-то на какой-то',
title: 'Web Basic',

View File

@@ -119,7 +119,9 @@ export const TableHeader: FC<
{columns.map(({ key, sortable = true, title }) => (
<TableHeadCell key={key} onClick={handleSort(key, sortable)}>
{title}
{sort && sort.key === key && <span>{sort.direction === 'asc' ? '▲' : '▼'}</span>}
{sort && sort.key === key && (
<span>{sort.direction === 'asc' ? '▲' : '▼'}</span>
)}
</TableHeadCell>
))}
</TableRow>

View File

@@ -3,9 +3,9 @@ import type { Meta, StoryObj } from '@storybook/react'
import { TextField } from './'
const meta = {
title: 'Components/TextField',
component: TextField,
tags: ['autodocs'],
title: 'Components/TextField',
} satisfies Meta<typeof TextField>
export default meta
@@ -28,8 +28,8 @@ export const Password: Story = {
export const Error: Story = {
args: {
errorMessage: 'Error message',
label: 'Input with error',
value: 'Wrong value',
errorMessage: 'Error message',
},
}

View File

@@ -1,8 +1,8 @@
import { useState } from 'react'
import { Button, Page, Slider, TextField, Typography } from '@/components'
import { DecksTable } from '@/components'
import { DeckDialog } from '@/components/decks/deck-dialog'
import { DecksTable } from '@/components/decks/decks-table'
import { DeleteDeckDialog } from '@/components/decks/delete-deck-dialog'
import { Pagination } from '@/components/ui/pagination'
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'

View File

@@ -1,35 +1,19 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { Tab } from '@/services'
import { PayloadAction, createSlice } from '@reduxjs/toolkit'
export const decksSlice = createSlice({
name: 'decks',
initialState: {
currentPage: 1,
currentTab: 'all' as Tab,
maxCards: undefined as number | undefined,
minCards: 0,
perPage: 10,
search: '',
minCards: 0,
maxCards: undefined as number | undefined,
currentTab: 'all' as Tab,
},
name: 'decks',
reducers: {
setCurrentPage: (state, action: PayloadAction<number>) => {
state.currentPage = action.payload
},
setPerPage: (state, action: PayloadAction<number>) => {
state.perPage = action.payload
},
setSearch: (state, action: PayloadAction<string>) => {
state.search = action.payload
},
setCurrentTab: (state, action: PayloadAction<Tab>) => {
state.currentTab = action.payload
},
setMinCards: (state, action: PayloadAction<number>) => {
state.minCards = action.payload
},
setMaxCards: (state, action: PayloadAction<number>) => {
state.maxCards = action.payload
resetCurrentPage: state => {
state.currentPage = 1
},
resetFilters: state => {
state.search = ''
@@ -37,8 +21,23 @@ export const decksSlice = createSlice({
state.minCards = 0
state.maxCards = undefined
},
resetCurrentPage: state => {
state.currentPage = 1
setCurrentPage: (state, action: PayloadAction<number>) => {
state.currentPage = action.payload
},
setCurrentTab: (state, action: PayloadAction<Tab>) => {
state.currentTab = action.payload
},
setMaxCards: (state, action: PayloadAction<number>) => {
state.maxCards = action.payload
},
setMinCards: (state, action: PayloadAction<number>) => {
state.minCards = action.payload
},
setPerPage: (state, action: PayloadAction<number>) => {
state.perPage = action.payload
},
setSearch: (state, action: PayloadAction<string>) => {
state.search = action.payload
},
},
})

View File

@@ -1,8 +1,8 @@
export type Pagination = {
totalPages: number
currentPage: number
itemsPerPage: number
totalItems: number
totalPages: number
}
export type Author = {
@@ -11,62 +11,62 @@ export type Author = {
}
export type Deck = {
id: string
userId: string
name: string
isPrivate: boolean
shots: number
cover?: string | null
rating: number
isDeleted: boolean | null
isBlocked?: boolean | null
created: string
updated: string
cardsCount: number
author: Author
cardsCount: number
cover?: null | string
created: string
id: string
isBlocked?: boolean | null
isDeleted: boolean | null
isPrivate: boolean
name: string
rating: number
shots: number
updated: string
userId: string
}
export type DecksResponse = {
items: Deck[]
maxCardsCount: number
pagination: Pagination
items: Deck[]
}
export type DeckResponse = Deck
export type CardsResponse = {
pagination: Pagination
items: Card[]
pagination: Pagination
}
export type Card = {
answer: string
answerImg?: null | string
created: string
deckId: string
grade: number
id: string
question: string
answer: string
deckId: string
questionImg?: string | null
answerImg?: string | null
created: string
updated: string
questionImg?: null | string
shots: number
grade: number
updated: string
userId: string
}
export type GetDecksArgs = {
minCardsCount?: number
maxCardsCount?: number
name?: string
authorId?: string
orderBy?: string
currentPage?: number
itemsPerPage?: number
maxCardsCount?: number
minCardsCount?: number
name?: string
orderBy?: string
}
export type CreateDeckArgs = {
name: string
isPrivate?: boolean
cover?: string
isPrivate?: boolean
name: string
}
export type UpdateDeckArgs = Partial<CreateDeckArgs> & { id: Deck['id'] }

View File

@@ -1,5 +1,7 @@
export function formatDate(date: string | undefined) {
if (!date) return ''
if (!date) {
return ''
}
return new Date(date).toLocaleDateString('ru-RU')
}