mirror of
https://github.com/quantum5/qcal.git
synced 2025-08-02 03:58:12 -04:00
61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
import React from 'react';
|
|
import {dateJDN} from '../gregorian';
|
|
|
|
type AppState<Selector> = {
|
|
selector: Selector;
|
|
todayJDN: number,
|
|
};
|
|
|
|
export default abstract class BaseApp<Selector> extends React.Component<{}, AppState<Selector>> {
|
|
state: AppState<Selector>;
|
|
|
|
protected constructor(props: {}) {
|
|
super(props);
|
|
const todayJDN = dateJDN(new Date());
|
|
|
|
this.state = {
|
|
selector: this.parsePath() || this.defaultSelector(todayJDN),
|
|
todayJDN,
|
|
};
|
|
this.updateStateFromURL = this.updateStateFromURL.bind(this);
|
|
}
|
|
|
|
abstract parsePath(): Selector | null;
|
|
|
|
abstract generatePath(selector: Selector): string;
|
|
|
|
abstract defaultSelector(todayJDN: number): Selector;
|
|
|
|
componentDidMount() {
|
|
window.addEventListener('popstate', this.updateStateFromURL);
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
window.removeEventListener('popstate', this.updateStateFromURL);
|
|
}
|
|
|
|
private updateStateFromURL(event: PopStateEvent) {
|
|
this.setState(event.state as Selector);
|
|
}
|
|
|
|
private updateURL() {
|
|
const path = this.generatePath(this.state.selector);
|
|
if (path !== window.location.pathname) {
|
|
window.history.pushState(this.state.selector, '', path);
|
|
}
|
|
}
|
|
|
|
setState(state: any, callback?: () => void) {
|
|
super.setState(state, () => {
|
|
this.updateURL();
|
|
callback?.();
|
|
});
|
|
}
|
|
|
|
onDateChange = (todayJDN: number) => {
|
|
this.setState({todayJDN});
|
|
};
|
|
|
|
abstract render(): JSX.Element;
|
|
}
|