Create core structure for the app

This commit is contained in:
Ceda EI 2020-12-21 00:49:50 +05:30
parent 3b0a212ad4
commit 90ba2410b9
10 changed files with 85 additions and 186 deletions

View File

@ -1,17 +1,12 @@
import React from "react";
import { Counter } from "./features/counter/Counter";
import "./App.css";
import { Grommet } from "grommet";
import Core from "./Core";
function App() {
return (
<div className="App">
<header className="App-header">
<Counter />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
</header>
</div>
<Grommet plain>
<Core />
</Grommet>
);
}

37
src/Core.js Normal file
View File

@ -0,0 +1,37 @@
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { setPlugin, selectCore } from "./coreSlice";
import * as plugins from "./plugins";
function Core() {
const coreState = useSelector(selectCore);
const dispatch = useDispatch();
console.log(plugins.default);
const plugin = plugins.default[coreState.plugin];
const props = {
data: coreState.data,
close: () => dispatch(setPlugin(false))
};
return <>
{plugin ? null :
<>
<p>Welcome to Honda!</p>
{Object.keys(plugins.default).map(
i => <p
onClick={() => dispatch(setPlugin(i))}
key={i}
>
{plugins.default[i].pluginName}
</p>)
}
</>
}
{plugin ?
React.cloneElement(plugin(), props)
:null
}
</>;
}
export default Core;

View File

@ -1,8 +1,8 @@
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import coreReducer from "../coreSlice";
export default configureStore({
reducer: {
counter: counterReducer,
core: coreReducer,
},
});

17
src/coreSlice.js Normal file
View File

@ -0,0 +1,17 @@
import { createSlice } from "@reduxjs/toolkit";
export const coreSlice = createSlice({
name: "core",
initialState: {
plugin: false,
data: {}
},
reducers: {
setPlugin: (state, action) => ({...state, plugin: action.payload}),
setData: (state, action) => ({...state, data: action.payload}),
}
});
export const { setPlugin, setData } = coreSlice.actions;
export const selectCore = state => state.core;
export default coreSlice.reducer;

View File

@ -1,58 +0,0 @@
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import {
decrement,
increment,
incrementByAmount,
incrementAsync,
selectCount,
} from "./counterSlice";
import styles from "./Counter.module.css";
export function Counter() {
const count = useSelector(selectCount);
const dispatch = useDispatch();
const [incrementAmount, setIncrementAmount] = useState("2");
return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
</div>
<div className={styles.row}>
<input
className={styles.textbox}
aria-label="Set increment amount"
value={incrementAmount}
onChange={e => setIncrementAmount(e.target.value)}
/>
<button
className={styles.button}
onClick={() => dispatch(incrementByAmount(Number(incrementAmount) || 0))}
>
Add Amount
</button>
<button
className={styles.asyncButton}
onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
>
Add Async
</button>
</div>
</div>
);
}

View File

@ -1,74 +0,0 @@
.row {
display: flex;
align-items: center;
justify-content: center;
}
.row:not(:last-child) {
margin-bottom: 16px;
}
.value {
font-size: 78px;
padding-left: 16px;
padding-right: 16px;
margin-top: 2px;
font-family: 'Courier New', Courier, monospace;
}
.button {
appearance: none;
background: none;
font-size: 32px;
padding-left: 12px;
padding-right: 12px;
outline: none;
border: 2px solid transparent;
color: rgb(112, 76, 182);
padding-bottom: 4px;
cursor: pointer;
background-color: rgba(112, 76, 182, 0.1);
border-radius: 2px;
transition: all 0.15s;
}
.textbox {
font-size: 32px;
padding: 2px;
width: 64px;
text-align: center;
margin-right: 8px;
}
.button:hover, .button:focus {
border: 2px solid rgba(112, 76, 182, 0.4);
}
.button:active {
background-color: rgba(112, 76, 182, 0.2);
}
.asyncButton {
composes: button;
position: relative;
margin-left: 8px;
}
.asyncButton:after {
content: "";
background-color: rgba(112, 76, 182, 0.15);
display: block;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
transition: width 1s linear, opacity 0.5s ease 1s;
}
.asyncButton:active:after {
width: 0%;
opacity: 1;
transition: 0s
}

View File

@ -1,42 +0,0 @@
import { createSlice } from "@reduxjs/toolkit";
export const counterSlice = createSlice({
name: "counter",
initialState: {
value: 0,
},
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn"t actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// The function below is called a thunk and allows us to perform async logic. It
// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
// will call the thunk with the `dispatch` function as the first argument. Async
// code can then be executed and other actions can be dispatched
export const incrementAsync = amount => dispatch => {
setTimeout(() => {
dispatch(incrementByAmount(amount));
}, 1000);
};
// The function below is called a selector and allows us to select a value from
// the state. Selectors can also be defined inline where they"re used instead of
// in the slice file. For example: `useSelector((state) => state.counter.value)`
export const selectCount = state => state.counter.value;
export default counterSlice.reducer;

6
src/plugins/index.js Normal file
View File

@ -0,0 +1,6 @@
import Mpd from "./mpd";
import Weather from "./weather";
export default {
mpd: Mpd,
weather: Weather,
};

9
src/plugins/mpd.js Normal file
View File

@ -0,0 +1,9 @@
import React from "react";
function Mpd() {
return <p> MPD Plugin </p>;
}
Mpd.pluginName = "Music Player";
export default Mpd;

9
src/plugins/weather.js Normal file
View File

@ -0,0 +1,9 @@
import React from "react";
function Weather() {
return <p> Weather Plugin </p>;
}
Weather.pluginName = "Weather";
export default Weather;