Skip to content

Commit

Permalink
refactor: implement feature sliced design (#113)
Browse files Browse the repository at this point in the history
* feat: add auth feature

* feat: add user feature

* refactor: add user constants

* feat: add kanban feature

* feat: add blocks folder header & sidebar

* refactor: add theme select to user feature

* style(prettier): add features folder to importOrder

* refactor: add dnd hooks and shared constants
  • Loading branch information
chertik77 authored Dec 25, 2024
1 parent 8ea48ce commit 3c41a9c
Show file tree
Hide file tree
Showing 157 changed files with 772 additions and 706 deletions.
4 changes: 2 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
"^(react)(/.*)?$",
"<THIRD_PARTY_MODULES>",
"",
"^components(/.*)?$",
"^features(/.*)?$",
"",
"^hooks(/.*)?$",
"^(pages|blocks|components|hooks)(/.*)?$",
"",
"^redux(/.*)?$",
"",
Expand Down
4 changes: 2 additions & 2 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import axios from 'axios'
import createAuthRefreshInterceptor from 'axios-auth-refresh'

import { authService } from 'features/auth/auth.service'

import { store } from 'redux/store'
import { logout, saveTokens } from 'redux/user.slice'

import { authService } from 'services'

export const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ThemeSelect } from 'features/user/components'

import { HeaderControls } from './HeaderControls'
import { HeaderThemeSelect } from './HeaderThemeSelect'
import { HeaderUserInfo } from './HeaderUserInfo'

export const Header = () => (
Expand All @@ -8,7 +9,7 @@ export const Header = () => (
duration-300 dark:bg-black'>
<HeaderControls />
<div className='flex items-center gap-3.5'>
<HeaderThemeSelect />
<ThemeSelect />
<HeaderUserInfo />
</div>
</header>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { BiSidebar } from 'react-icons/bi'
import { useModal } from 'react-modal-state'

import { BurgerMenu } from 'blocks/sidebar/BurgerMenu'
import { useAppDispatch, useAppSelector } from 'hooks/redux'

import { selectIsSidebarOpen, setIsSidebarOpen } from 'redux/sidebar.slice'

import { BurgerMenu } from '../modals/BurgerMenu'

export const HeaderControls = () => {
const { open } = useModal(BurgerMenu)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as Avatar from '@radix-ui/react-avatar'
import { useModal } from 'react-modal-state'

import { EditProfileModal } from 'features/user/components/modals'

import { useAppSelector } from 'hooks/redux'

import { selectUser } from 'redux/user.slice'

import { EditProfileModal } from '../modals'

export const HeaderUserInfo = () => {
const { name, avatar } = useAppSelector(selectUser)

Expand Down
1 change: 0 additions & 1 deletion src/components/dashboard/index.ts → src/blocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './board/Board'
export * from './header/Header'
export * from './sidebar/Sidebar'
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useModalInstance } from 'react-modal-state'
import { Modal } from 'react-responsive-modal'

import { SidebarBoardsList } from 'components/dashboard/sidebar/SidebarBoardsList'
import { SidebarLogo } from 'components/dashboard/sidebar/SidebarLogo'
import { SidebarLogoutBtn } from 'components/dashboard/sidebar/SidebarLogoutBtn'
import { SidebarMyBoardsInfo } from 'components/dashboard/sidebar/SidebarMyBoardsInfo'
import { SidebarUserSupport } from 'components/dashboard/sidebar/SidebarUserSupport'
import { SidebarBoardsList } from './SidebarBoardsList'
import { SidebarLogo } from './SidebarLogo'
import { SidebarLogoutBtn } from './SidebarLogoutBtn'
import { SidebarMyBoardsInfo } from './SidebarMyBoardsInfo'
import { SidebarUserSupport } from './SidebarUserSupport'

export const BurgerMenu = () => {
const { isOpen, close } = useModalInstance()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as ScrollArea from '@radix-ui/react-scroll-area'

import { Scrollbar } from 'components/ui'

import { useAppSelector } from 'hooks/redux'

import { selectIsSidebarOpen } from 'redux/sidebar.slice'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { Indicator, Item, Root } from '@radix-ui/react-radio-group'
import { useQuery } from '@tanstack/react-query'
import { useModal } from 'react-modal-state'
import { useNavigate } from 'react-router-dom'

import { Loader } from 'components/ui'
import { useGetAllBoards, useGetBoardId } from 'features/kanban/board/hooks'

import { useGetBoardId } from 'hooks/board'
import { Loader } from 'components/ui'

import { CacheKeys, Pages } from 'config'
import { boardService } from 'services'
import { Pages } from 'config'

import { cn } from 'lib'

import { BurgerMenu } from '../modals'
import { BurgerMenu } from './BurgerMenu'
import { SidebarListActiveItem } from './SidebarListActiveItem'

export const SidebarBoardsList = () => {
Expand All @@ -22,10 +20,7 @@ export const SidebarBoardsList = () => {

const { close: closeBurgerMenu } = useModal(BurgerMenu)

const { data, isPending } = useQuery({
queryKey: [CacheKeys.Boards],
queryFn: boardService.getAllBoards
})
const { data, isPending } = useGetAllBoards()

return isPending ? (
<div className='flex h-4xl items-center gap-2 pl-3.5 violet:text-white tablet:pl-6'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Board } from 'types'
import type { Board } from 'features/kanban/board/board.types'

import { useModal } from 'react-modal-state'

import { useDeleteBoard } from 'hooks/board'
import { EditBoardModal } from 'features/kanban/board/components/modals'
import { useDeleteBoard } from 'features/kanban/board/hooks'

import { BurgerMenu, EditBoardModal } from '../modals'
import { BurgerMenu } from './BurgerMenu'

export const SidebarListActiveItem = ({
board: { icon, title, background }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link } from 'react-router-dom'

import { Pages } from 'config'

import { BurgerMenu } from '../modals'
import { BurgerMenu } from './BurgerMenu'

export const SidebarLogo = () => {
const { close: closeBurgerMenu } = useModal(BurgerMenu)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLogoutUser } from 'hooks/auth'
import { useLogoutUser } from 'features/auth/hooks'

export const SidebarLogoutBtn = () => {
const { mutate, isPending } = useLogoutUser()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useModal } from 'react-modal-state'

import { NewBoardModal } from 'features/kanban/board/components/modals'

import { cn } from 'lib'

import { BurgerMenu, NewBoardModal } from '../modals'
import { BurgerMenu } from './BurgerMenu'

export const SidebarMyBoardsInfo = () => {
const { open } = useModal(NewBoardModal)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useModal } from 'react-modal-state'

import { BurgerMenu, NeedHelpModal } from '../modals'
import { NeedHelpModal } from 'features/user/components/modals'

import { BurgerMenu } from './BurgerMenu'

export const SidebarUserSupport = () => {
const { open } = useModal(NeedHelpModal)
Expand Down
33 changes: 7 additions & 26 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,18 @@
import { useEffect } from 'react'
import { useQuery } from '@tanstack/react-query'
import { AuthPage, DashboardPage, HomePage } from 'pages'
import { Route, Routes } from 'react-router-dom'

import { PrivateRoute, PublicOnlyRoute } from 'components/routes'

import { useAppDispatch, useAppSelector } from 'hooks/redux'
import { Board } from 'features/kanban/board/components/Board'
import { useGetCurrentUser } from 'features/user/hooks'

import { selectIsLoggedIn, updateUser } from 'redux/user.slice'
import { PrivateRoute, PublicOnlyRoute } from 'components/routes'
import { AuthPage, DashboardPage, HomePage } from 'pages'

import { CacheKeys, Pages } from 'config'
import { userService } from 'services'
import { Pages } from 'config'

import { Board } from './dashboard'
import { EmptyBoard } from './dashboard/board/EmptyBoard'
import { EmptyBoard } from '../features/kanban/board/components/EmptyBoard'
import { Layout } from './Layout'

export const App = () => {
const isLoggedIn = useAppSelector(selectIsLoggedIn)

const dispatch = useAppDispatch()

const { data, isSuccess } = useQuery({
queryKey: [CacheKeys.User],
queryFn: userService.getCurrentUser,
enabled: isLoggedIn
})

useEffect(() => {
if (isSuccess) {
dispatch(updateUser(data))
}
}, [data, dispatch, isSuccess])
useGetCurrentUser()

return (
<Routes>
Expand Down
7 changes: 0 additions & 7 deletions src/components/dashboard/modals/index.ts

This file was deleted.

4 changes: 1 addition & 3 deletions src/components/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export * from './Button'
export * from './Scrollbar'
export * from './DatePicker'
export * from './Field'
export * from './Loader'
export * from './Modal'
export * from './RadioInput'
export * from './Scrollbar'
27 changes: 0 additions & 27 deletions src/config/api-endpoints.config.ts

This file was deleted.

26 changes: 0 additions & 26 deletions src/config/cache-keys.config.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export * from './api-endpoints.config'
export * from './cache-keys.config'
export * from './pages-url.config'
3 changes: 0 additions & 3 deletions src/constants/deadlines.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/constants/priorities.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/constants/themes.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,5 @@ export const SignupSchema = v.object({
...SigninSchema.entries
})

export const EditUserSchema = v.partial(
v.object({
...SignupSchema.entries,
avatar: v.instance(File)
})
)

export const HelpSchema = v.object({
email: SigninSchema.entries.email,
comment: v.string([
v.toTrimmed(),
v.minLength(5, 'Please enter at least 5 characters.')
])
})

export type SigninSchema = v.Output<typeof SigninSchema>
export type SignupSchema = v.Output<typeof SignupSchema>
export type EditUserSchema = v.Output<typeof EditUserSchema>
export type HelpSchema = v.Output<typeof HelpSchema>
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { AxiosAuthRefreshRequestConfig } from 'axios-auth-refresh'
import type { SigninSchema, SignupSchema } from 'lib/schemas'
import type { AuthResponse, Tokens } from 'types'
import type { SigninSchema, SignupSchema } from './auth.schema'
import type { AuthResponse, Tokens } from './auth.types'

import { axiosInstance } from 'api'
import { ApiEndpoints } from 'config'

import { AuthApiEndpoints } from './config'

export const authService = {
async signup(data: SignupSchema) {
const response = await axiosInstance.post<AuthResponse>(
ApiEndpoints.Signup,
AuthApiEndpoints.Signup,
data
)

Expand All @@ -21,7 +22,7 @@ export const authService = {
}

const response = await axiosInstance.post<AuthResponse>(
ApiEndpoints.Signin,
AuthApiEndpoints.Signin,
data,
requestConfig
)
Expand All @@ -31,18 +32,18 @@ export const authService = {

async signinWithGoogle(code: string) {
const response = await axiosInstance.post<AuthResponse>(
ApiEndpoints.Google,
AuthApiEndpoints.Google,
{ code }
)

return response.data
},

getTokens(data: { refreshToken: string }) {
return axiosInstance.post<Tokens>(ApiEndpoints.Tokens, data)
return axiosInstance.post<Tokens>(AuthApiEndpoints.Tokens, data)
},

async logout() {
await axiosInstance.post(ApiEndpoints.Logout)
await axiosInstance.post(AuthApiEndpoints.Logout)
}
}
Loading

0 comments on commit 3c41a9c

Please sign in to comment.