-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
290 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
import {Provider} from 'react-redux'; | ||
|
||
import store from './store'; | ||
|
||
import {PageNotificationContainer} from './components/PageNotificationContainer'; | ||
import {TextFeedbackContainer} from './components/TextFeedbackContainer'; | ||
|
||
export default function () { | ||
return ( | ||
<div className='tb-app-root'> | ||
<PageNotificationContainer /> | ||
</div> | ||
<Provider store={store}> | ||
<div className='tb-app-root'> | ||
<PageNotificationContainer /> | ||
<TextFeedbackContainer /> | ||
</div> | ||
</Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import {useSelector} from 'react-redux'; | ||
import {RootState} from '../store'; | ||
import {TextFeedbackLocation} from '../store/textFeedbackSlice'; | ||
|
||
export function TextFeedbackContainer () { | ||
const currentMessage = useSelector((state: RootState) => state.textFeedback.current); | ||
|
||
// TODO: dont judge me for this im just duplicating how it was done before. | ||
// eventually we will have a way to do scoped component styles and this will | ||
// be better | ||
const style = currentMessage && currentMessage.location === TextFeedbackLocation.BOTTOM | ||
? { | ||
left: '5px', | ||
bottom: '40px', | ||
top: 'auto', | ||
position: 'fixed', | ||
} as const | ||
: { | ||
transform: 'translate(-50%)', | ||
} as const; | ||
|
||
return ( | ||
<> | ||
{currentMessage && ( | ||
<div id='tb-feedback-window' className={currentMessage.kind} style={style}> | ||
<span className='tb-feedback-text'>{currentMessage.message}</span> | ||
</div> | ||
)} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import {combineReducers, configureStore, ThunkAction, UnknownAction} from '@reduxjs/toolkit'; | ||
import textFeedbackReducer from './textFeedbackSlice'; | ||
|
||
const rootReducer = combineReducers({ | ||
textFeedback: textFeedbackReducer, | ||
}); | ||
|
||
const store = configureStore({ | ||
reducer: rootReducer, | ||
}); | ||
export default store; | ||
|
||
// TS concerns - see https://redux.js.org/usage/usage-with-typescript#define-root-state-and-dispatch-types | ||
export type RootState = ReturnType<typeof rootReducer>; | ||
export type AppDispatch = typeof store.dispatch; | ||
export type AppThunk<ReturnType = void> = ThunkAction< | ||
ReturnType, | ||
RootState, | ||
unknown, | ||
UnknownAction | ||
>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {createSlice, type PayloadAction} from '@reduxjs/toolkit'; | ||
import {type AppThunk} from '.'; | ||
|
||
// TODO: remove `TBui.FEEDBACK_*` constants in favor of this enum | ||
export enum TextFeedbackKind { | ||
NEUTRAL = 'neutral', | ||
POSITIVE = 'positive', | ||
NEGATIVE = 'negative', | ||
} | ||
|
||
// TODO: remove `TBui.DISPLAY_*` constants in favor of this enum | ||
export enum TextFeedbackLocation { | ||
CENTER = 'center', | ||
BOTTOM = 'bottom', | ||
} | ||
|
||
/** A text feedback message to be displayed. */ | ||
export interface TextFeedback { | ||
message: string; | ||
kind: TextFeedbackKind; | ||
location: TextFeedbackLocation; | ||
} | ||
|
||
// alright time for redux shit | ||
|
||
interface TextFeedbackState { | ||
current: TextFeedback | null; | ||
} | ||
export const textFeedbackSlice = createSlice({ | ||
name: 'textFeedback', | ||
initialState: { | ||
current: null, | ||
} as TextFeedbackState, | ||
reducers: { | ||
set (state, action: PayloadAction<TextFeedback>) { | ||
state.current = action.payload; | ||
}, | ||
clear (state) { | ||
state.current = null; | ||
}, | ||
}, | ||
}); | ||
export default textFeedbackSlice.reducer; | ||
export const {set, clear} = textFeedbackSlice.actions; | ||
|
||
let removeTextFeedbackTimeout: number | null = null; | ||
export const showTextFeedback = (message: TextFeedback, duration = 3000): AppThunk => dispatch => { | ||
// cancel any pending removal from previous messages | ||
if (removeTextFeedbackTimeout) { | ||
clearTimeout(removeTextFeedbackTimeout); | ||
} | ||
|
||
// display the message | ||
dispatch(set(message)); | ||
|
||
// queue the message to be removed after the duration | ||
removeTextFeedbackTimeout = window.setTimeout(() => { | ||
dispatch(clear()); | ||
removeTextFeedbackTimeout = null; | ||
}, duration); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.