mirror of
https://github.com/NohamR/gitprofile.git
synced 2026-05-25 04:17:13 +00:00
Migrate from redux to context
This commit is contained in:
41
src/App.js
41
src/App.js
@@ -1,26 +1,25 @@
|
||||
import axios from "axios";
|
||||
import { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
|
||||
import AvatarCard from "./components/AvatarCard";
|
||||
import ErrorPage from "./components/ErrorPage";
|
||||
import ThemeChanger from "./components/ThemeChanger";
|
||||
import config from "./config";
|
||||
import moment from 'moment';
|
||||
import { setLoading } from "./store/slices/loadingSlice";
|
||||
import { setProfile } from "./store/slices/profileSlice";
|
||||
import Details from "./components/Details";
|
||||
import Skill from "./components/Skill";
|
||||
import Experience from "./components/Experience";
|
||||
import Education from "./components/Education";
|
||||
import Project from "./components/Project";
|
||||
import { setRepo } from "./store/slices/repoSlice";
|
||||
import Blog from "./components/Blog";
|
||||
import MetaTags from "./components/MetaTags";
|
||||
import { LoadingContext } from "./contexts/LoadingContext";
|
||||
import { ThemeContext } from "./contexts/ThemeContext";
|
||||
|
||||
function App() {
|
||||
const dispatch = useDispatch();
|
||||
const theme = useSelector(state => state.theme);
|
||||
|
||||
const [theme] = useContext(ThemeContext);
|
||||
const [, setLoading] = useContext(LoadingContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
const [repo, setRepo] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const [rateLimit, setRateLimit] = useState(null);
|
||||
|
||||
@@ -43,7 +42,7 @@ function App() {
|
||||
company: data.company ? data.company : ''
|
||||
}
|
||||
|
||||
dispatch(setProfile(profileData));
|
||||
setProfile(profileData);
|
||||
})
|
||||
.then(() => {
|
||||
let excludeRepo = ``;
|
||||
@@ -64,7 +63,7 @@ function App() {
|
||||
.then(response => {
|
||||
let data = response.data;
|
||||
|
||||
dispatch(setRepo(data.items));
|
||||
setRepo(data.items);
|
||||
})
|
||||
.catch((error) => {
|
||||
handleError(error);
|
||||
@@ -74,9 +73,9 @@ function App() {
|
||||
handleError(error);
|
||||
})
|
||||
.finally(() => {
|
||||
dispatch(setLoading(false));
|
||||
setLoading(false);
|
||||
});
|
||||
}, [dispatch])
|
||||
}, [setLoading])
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
@@ -104,7 +103,7 @@ function App() {
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<MetaTags/>
|
||||
<MetaTags profile={profile}/>
|
||||
<div className="fade-in h-screen">
|
||||
|
||||
{
|
||||
@@ -144,20 +143,20 @@ function App() {
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
{
|
||||
!config.themeConfig.disableSwitch && (
|
||||
<ThemeChanger />
|
||||
<ThemeChanger/>
|
||||
)
|
||||
}
|
||||
<AvatarCard />
|
||||
<Details />
|
||||
<Skill />
|
||||
<Experience />
|
||||
<Education />
|
||||
<AvatarCard profile={profile}/>
|
||||
<Details profile={profile}/>
|
||||
<Skill/>
|
||||
<Experience/>
|
||||
<Education/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:col-span-2 col-span-1">
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
<Project />
|
||||
<Blog />
|
||||
<Project repo={repo}/>
|
||||
<Blog/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { useSelector } from "react-redux";
|
||||
import { fallbackImage, skeleton } from "../helpers/utils";
|
||||
import LazyImage from "./LazyImage";
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext } from "react";
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
|
||||
const AvatarCard = () => {
|
||||
const profile = useSelector(state => state.profile);
|
||||
const loading = useSelector(state => state.loading);
|
||||
const AvatarCard = (props) => {
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
return (
|
||||
<div className="card shadow-lg compact bg-base-100">
|
||||
<div className="grid place-items-center py-8">
|
||||
{
|
||||
loading ? (
|
||||
(loading || !props.profile) ? (
|
||||
<div className="avatar opacity-90">
|
||||
<div className="mb-8 rounded-full w-32 h-32">
|
||||
{
|
||||
@@ -27,8 +28,8 @@ const AvatarCard = () => {
|
||||
<div className="mb-8 rounded-full w-32 h-32 ring ring-primary ring-offset-base-100 ring-offset-2">
|
||||
{
|
||||
<LazyImage
|
||||
src={profile.avatar ? profile.avatar : fallbackImage}
|
||||
alt={profile.name}
|
||||
src={props.profile.avatar ? props.profile.avatar : fallbackImage}
|
||||
alt={props.profile.name}
|
||||
placeholder={
|
||||
skeleton({
|
||||
width: 'w-full',
|
||||
@@ -45,16 +46,16 @@ const AvatarCard = () => {
|
||||
<div className="text-center mx-auto px-8">
|
||||
<h5 className="font-bold text-2xl">
|
||||
{
|
||||
loading ? (
|
||||
(loading || !props.profile) ? (
|
||||
skeleton({ width: 'w-48', height: 'h-8' })
|
||||
) : <span className="opacity-70">{profile.name}</span>
|
||||
) : <span className="opacity-70">{props.profile.name}</span>
|
||||
}
|
||||
</h5>
|
||||
<div className="mt-3 text-base-content text-opacity-60">
|
||||
{
|
||||
loading ? (
|
||||
(loading || !props.profile) ? (
|
||||
skeleton({ width: 'w-48', height: 'h-5' })
|
||||
) : profile.bio
|
||||
) : props.profile.bio
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,4 +64,8 @@ const AvatarCard = () => {
|
||||
)
|
||||
}
|
||||
|
||||
AvatarCard.propTypes = {
|
||||
profile: PropTypes.object
|
||||
}
|
||||
|
||||
export default AvatarCard;
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getDevtoArticle, getMediumArticle } from "article-api";
|
||||
import moment from "moment";
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
import { Fragment, useContext, useEffect, useState } from "react";
|
||||
import { CgHashtag } from 'react-icons/cg';
|
||||
import { useSelector } from "react-redux";
|
||||
import config from "../config";
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
import { ga, skeleton } from "../helpers/utils";
|
||||
import LazyImage from "./LazyImage";
|
||||
|
||||
@@ -23,7 +23,7 @@ const displaySection = () => {
|
||||
|
||||
const Blog = () => {
|
||||
const [articles, setArticles] = useState(null);
|
||||
const loading = useSelector(state => state.loading);
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (displaySection()) {
|
||||
|
||||
@@ -5,13 +5,14 @@ import { GrLinkedinOption } from 'react-icons/gr';
|
||||
import { CgDribbble } from 'react-icons/cg';
|
||||
import { RiPhoneFill } from 'react-icons/ri';
|
||||
import { FaBehanceSquare, FaBuilding, FaDev, FaFacebook, FaGlobe } from 'react-icons/fa';
|
||||
import { useSelector } from 'react-redux';
|
||||
import config from '../config';
|
||||
import { skeleton } from '../helpers/utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext } from 'react';
|
||||
import { LoadingContext } from '../contexts/LoadingContext';
|
||||
|
||||
const Details = () => {
|
||||
const profile = useSelector(state => state.profile);
|
||||
const loading = useSelector(state => state.loading);
|
||||
const Details = (props) => {
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const renderSkeleton = () => {
|
||||
let array = [];
|
||||
@@ -34,24 +35,24 @@ const Details = () => {
|
||||
<div className="card-body">
|
||||
<ul className="menu row-span-3 bg-base-100 text-base-content text-opacity-60">
|
||||
{
|
||||
loading ? renderSkeleton() : (
|
||||
(loading || !props.profile) ? renderSkeleton() : (
|
||||
<>
|
||||
{
|
||||
profile && profile.location && (
|
||||
props.profile.location && (
|
||||
<li>
|
||||
<span>
|
||||
<MdLocationOn className="mr-2" />
|
||||
{profile.location}
|
||||
{props.profile.location}
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
{
|
||||
profile && profile.company && (
|
||||
props.profile.company && (
|
||||
<li>
|
||||
<span>
|
||||
<FaBuilding className="mr-2" />
|
||||
{profile.company}
|
||||
{props.profile.company}
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
@@ -247,4 +248,8 @@ const Details = () => {
|
||||
)
|
||||
}
|
||||
|
||||
Details.propTypes = {
|
||||
profile: PropTypes.object
|
||||
}
|
||||
|
||||
export default Details;
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useSelector } from "react-redux";
|
||||
import config from "../config";
|
||||
import { GoPrimitiveDot } from 'react-icons/go';
|
||||
import { skeleton } from "../helpers/utils";
|
||||
import { useContext } from "react";
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
|
||||
const Education = () => {
|
||||
const loading = useSelector(state => state.loading);
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const renderSkeleton = () => {
|
||||
let array = [];
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useSelector } from "react-redux";
|
||||
import config from "../config";
|
||||
import { GoPrimitiveDot } from 'react-icons/go';
|
||||
import { skeleton } from "../helpers/utils";
|
||||
import { useContext } from "react";
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
|
||||
const Experience = () => {
|
||||
const loading = useSelector(state => state.loading);
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const renderSkeleton = () => {
|
||||
let array = [];
|
||||
@@ -44,9 +45,11 @@ const Experience = () => {
|
||||
<li>
|
||||
<div className="pb-0-important mx-3">
|
||||
<h5 className="card-title">
|
||||
{loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
|
||||
<span className="opacity-70">Experience</span>
|
||||
)}
|
||||
{
|
||||
loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
|
||||
<span className="opacity-70">Experience</span>
|
||||
)
|
||||
}
|
||||
</h5>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { Fragment, useContext } from 'react';
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useSelector } from 'react-redux';
|
||||
import config from '../config';
|
||||
import { isThemeDarkish } from '../helpers/utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ThemeContext } from '../contexts/ThemeContext';
|
||||
|
||||
const MetaTags = () => {
|
||||
const profile = useSelector(state => state.profile);
|
||||
const theme = useSelector(state => state.theme);
|
||||
const MetaTags = (props) => {
|
||||
const [theme] = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{
|
||||
profile && (
|
||||
props.profile && (
|
||||
<Helmet>
|
||||
{
|
||||
config.googleAnalytics.id && (
|
||||
@@ -33,25 +33,25 @@ const MetaTags = () => {
|
||||
</script>
|
||||
)
|
||||
}
|
||||
<title>Portfolio of {profile.name}</title>
|
||||
<title>Portfolio of {props.profile.name}</title>
|
||||
<meta name="theme-color" content={isThemeDarkish(theme) ? '#000000' : '#ffffff'}/>
|
||||
|
||||
<meta name="description" content={profile.bio} />
|
||||
<meta name="description" content={props.profile.bio} />
|
||||
|
||||
<meta itemprop="name" content={`Portfolio of ${profile.name}`} />
|
||||
<meta itemprop="description" content={profile.bio} />
|
||||
<meta itemprop="image" content={profile.avatar} />
|
||||
<meta itemprop="name" content={`Portfolio of ${props.profile.name}`} />
|
||||
<meta itemprop="description" content={props.profile.bio} />
|
||||
<meta itemprop="image" content={props.profile.avatar} />
|
||||
|
||||
<meta property="og:url" content={typeof config.social.website !== 'undefined' ? config.social.website : ''} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={`Portfolio of ${profile.name}`} />
|
||||
<meta property="og:description" content={profile.bio} />
|
||||
<meta property="og:image" content={profile.avatar} />
|
||||
<meta property="og:title" content={`Portfolio of ${props.profile.name}`} />
|
||||
<meta property="og:description" content={props.profile.bio} />
|
||||
<meta property="og:image" content={props.profile.avatar} />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={`Portfolio of ${profile.name}`} />
|
||||
<meta name="twitter:description" content={profile.bio} />
|
||||
<meta name="twitter:image" content={profile.avatar} />
|
||||
<meta name="twitter:title" content={`Portfolio of ${props.profile.name}`} />
|
||||
<meta name="twitter:description" content={props.profile.bio} />
|
||||
<meta name="twitter:image" content={props.profile.avatar} />
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
@@ -59,4 +59,8 @@ const MetaTags = () => {
|
||||
)
|
||||
}
|
||||
|
||||
MetaTags.propTypes = {
|
||||
profile: PropTypes.object
|
||||
}
|
||||
|
||||
export default MetaTags;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Fragment } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Fragment, useContext } from "react";
|
||||
import { ga, languageColor, skeleton } from "../helpers/utils";
|
||||
import { AiOutlineStar, AiOutlineFork } from 'react-icons/ai';
|
||||
import config from "../config";
|
||||
import PropTypes from 'prop-types';
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
|
||||
const Project = () => {
|
||||
const loading = useSelector(state => state.loading);
|
||||
const repo = useSelector(state => state.repo);
|
||||
const Project = (props) => {
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const renderSkeleton = () => {
|
||||
let array = [];
|
||||
@@ -51,7 +51,7 @@ const Project = () => {
|
||||
}
|
||||
|
||||
const renderProjects = () => {
|
||||
return repo.map((item, index) => (
|
||||
return props.repo.map((item, index) => (
|
||||
<div
|
||||
className="card shadow-lg compact bg-base-100 cursor-pointer"
|
||||
key={index}
|
||||
@@ -146,7 +146,7 @@ const Project = () => {
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{(loading || !repo) ? renderSkeleton() : renderProjects()}
|
||||
{(loading || !props.repo) ? renderSkeleton() : renderProjects()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,4 +155,8 @@ const Project = () => {
|
||||
)
|
||||
}
|
||||
|
||||
Project.propTypes = {
|
||||
repo: PropTypes.array
|
||||
}
|
||||
|
||||
export default Project;
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useSelector } from "react-redux";
|
||||
import { useContext } from "react";
|
||||
import config from "../config";
|
||||
import { LoadingContext } from "../contexts/LoadingContext";
|
||||
import { skeleton } from "../helpers/utils";
|
||||
|
||||
const Skill = () => {
|
||||
const loading = useSelector(state => state.loading);
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const renderSkeleton = () => {
|
||||
let array = [];
|
||||
@@ -26,9 +27,11 @@ const Skill = () => {
|
||||
<div className="card-body">
|
||||
<div className="mx-3">
|
||||
<h5 className="card-title">
|
||||
{loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
|
||||
<span className="opacity-70">Tech Stack</span>
|
||||
)}
|
||||
{
|
||||
loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
|
||||
<span className="opacity-70">Tech Stack</span>
|
||||
)
|
||||
}
|
||||
</h5>
|
||||
</div>
|
||||
<div className="p-3 flow-root">
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { setTheme } from '../store/slices/themeSlice';
|
||||
import config from '../config';
|
||||
import { skeleton } from '../helpers/utils';
|
||||
import { AiOutlineControl } from 'react-icons/ai';
|
||||
import { useContext } from 'react';
|
||||
import { ThemeContext } from '../contexts/ThemeContext';
|
||||
import { LoadingContext } from '../contexts/LoadingContext';
|
||||
|
||||
const ThemeChanger = () => {
|
||||
const dispatch = useDispatch();
|
||||
const theme = useSelector(state => state.theme);
|
||||
const loading = useSelector(state => state.loading);
|
||||
const [theme, setTheme] = useContext(ThemeContext);
|
||||
const [loading] = useContext(LoadingContext);
|
||||
|
||||
const changeTheme = (e, selectedTheme) => {
|
||||
e.preventDefault();
|
||||
dispatch(setTheme(selectedTheme));
|
||||
document.querySelector('html').setAttribute('data-theme', selectedTheme);
|
||||
localStorage.setItem('ezprofileTheme', selectedTheme);
|
||||
|
||||
setTheme(selectedTheme);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -26,7 +29,9 @@ const ThemeChanger = () => {
|
||||
}
|
||||
</h5>
|
||||
<span className="text-base-content text-opacity-40 capitalize text-sm">
|
||||
{loading ? skeleton({ width: 'w-16', height: 'h-5' }) : (theme === config.themeConfig.default ? 'Default' : theme)}
|
||||
{
|
||||
loading ? skeleton({ width: 'w-16', height: 'h-5' }) : (theme === config.themeConfig.default ? 'Default' : theme)
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-0">
|
||||
|
||||
15
src/contexts/LoadingContext.js
Normal file
15
src/contexts/LoadingContext.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createContext, useState } from "react";
|
||||
|
||||
const initialValue = true;
|
||||
|
||||
export const LoadingContext = createContext();
|
||||
|
||||
export const LoadingProvider = (props) => {
|
||||
const [loading, setLoading] = useState(initialValue);
|
||||
|
||||
return (
|
||||
<LoadingContext.Provider value={[loading, setLoading]}>
|
||||
{props.children}
|
||||
</LoadingContext.Provider>
|
||||
);
|
||||
}
|
||||
16
src/contexts/ThemeContext.js
Normal file
16
src/contexts/ThemeContext.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { createContext, useState } from "react";
|
||||
import { getInitialTheme } from "../helpers/utils";
|
||||
|
||||
const initialValue = getInitialTheme();
|
||||
|
||||
export const ThemeContext = createContext();
|
||||
|
||||
export const ThemeProvider = (props) => {
|
||||
const [theme, setTheme] = useState(initialValue);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={[theme, setTheme]}>
|
||||
{props.children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import config from "../config";
|
||||
import colors from './colors.json';
|
||||
|
||||
export const getThemeValue = () => {
|
||||
export const getInitialTheme = () => {
|
||||
if (config.themeConfig.disableSwitch) {
|
||||
return config.themeConfig.default;
|
||||
}
|
||||
|
||||
16
src/index.js
16
src/index.js
@@ -2,18 +2,20 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.scss';
|
||||
import App from './App';
|
||||
import { Provider } from 'react-redux';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import { store } from './store/store';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { ThemeProvider } from './contexts/ThemeContext';
|
||||
import { LoadingProvider } from './contexts/LoadingContext';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<HelmetProvider>
|
||||
<App/>
|
||||
</HelmetProvider>
|
||||
</Provider>
|
||||
<ThemeProvider>
|
||||
<LoadingProvider>
|
||||
<HelmetProvider>
|
||||
<App/>
|
||||
</HelmetProvider>
|
||||
</LoadingProvider>
|
||||
</ThemeProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = true;
|
||||
|
||||
export const loadingSlice = createSlice({
|
||||
name: 'loading',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
setLoading: (state, action) => {
|
||||
state = action.payload;
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const { setLoading } = loadingSlice.actions;
|
||||
|
||||
export default loadingSlice.reducer;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = null;
|
||||
|
||||
export const profileSlice = createSlice({
|
||||
name: 'profile',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
setProfile: (state, action) => {
|
||||
state = action.payload;
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const { setProfile } = profileSlice.actions;
|
||||
|
||||
export default profileSlice.reducer;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = null;
|
||||
|
||||
export const repoSlice = createSlice({
|
||||
name: 'repo',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
setRepo: (state, action) => {
|
||||
state = action.payload;
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const { setRepo } = repoSlice.actions;
|
||||
|
||||
export default repoSlice.reducer;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { getThemeValue } from '../../helpers/utils';
|
||||
|
||||
const initialState = getThemeValue();
|
||||
|
||||
export const themeSlice = createSlice({
|
||||
name: 'theme',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
setTheme: (state, action) => {
|
||||
state = action.payload;
|
||||
|
||||
document.querySelector('html').setAttribute('data-theme', state);
|
||||
localStorage.setItem('ezprofileTheme', state);
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const { setTheme } = themeSlice.actions;
|
||||
|
||||
export default themeSlice.reducer;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { combineReducers, configureStore } from '@reduxjs/toolkit';
|
||||
import loadingSlice from './slices/loadingSlice';
|
||||
import profileSlice from './slices/profileSlice';
|
||||
import repoSlice from './slices/repoSlice';
|
||||
import themeSlice from './slices/themeSlice';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
profile: profileSlice,
|
||||
theme: themeSlice,
|
||||
loading: loadingSlice,
|
||||
repo: repoSlice,
|
||||
})
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: rootReducer
|
||||
})
|
||||
Reference in New Issue
Block a user