mirror of
https://github.com/mgerb/classic-wow-forums
synced 2026-01-10 17:12:48 +00:00
client - support for admin/mod users
This commit is contained in:
BIN
client/app/assets/avatars/Caydiem.gif
Normal file
BIN
client/app/assets/avatars/Caydiem.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
client/app/assets/avatars/Ordinn.gif
Normal file
BIN
client/app/assets/avatars/Ordinn.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -29,9 +29,13 @@ export const initializeAxios = (): Promise<void> => {
|
|||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
|
nprogress.done();
|
||||||
|
|
||||||
// if code is unauthorized (401) then logout if already logged in
|
// if code is unauthorized (401) then logout if already logged in
|
||||||
if (error.response.status === 401 && userStore.user) {
|
if (error.response.status === 401 && userStore.user) {
|
||||||
userStore.resetUser();
|
userStore.resetUser();
|
||||||
|
// redirect back to home page upon logout
|
||||||
|
window.location.pathname = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|||||||
@@ -48,6 +48,5 @@
|
|||||||
|
|
||||||
&__error-message {
|
&__error-message {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: red;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export class Editor extends React.Component<Props, State> {
|
|||||||
<div>{this.state.contentCharacterCount}/2000</div>
|
<div>{this.state.contentCharacterCount}/2000</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="editor__error-message">{this.state.errorMessage}</div>
|
<div className="editor__error-message red">{this.state.errorMessage}</div>
|
||||||
|
|
||||||
<div><label>Preview</label></div>
|
<div><label>Preview</label></div>
|
||||||
<div className="markdown-container">
|
<div className="markdown-container">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link, RouteComponentProps } from 'react-router-dom';
|
import { Link, RouteComponentProps } from 'react-router-dom';
|
||||||
import { inject, observer } from 'mobx-react';
|
import { inject, observer } from 'mobx-react';
|
||||||
|
import { orderBy } from 'lodash';
|
||||||
import { ThreadService } from '../../services';
|
import { ThreadService } from '../../services';
|
||||||
import { Editor, ForumNav, LoginButton, ScrollToTop } from '../../components';
|
import { Editor, ForumNav, LoginButton, ScrollToTop } from '../../components';
|
||||||
import { ThreadModel } from '../../model';
|
import { ThreadModel } from '../../model';
|
||||||
@@ -8,6 +9,8 @@ import { UserStore } from '../../stores/user-store';
|
|||||||
import './forum.scss';
|
import './forum.scss';
|
||||||
import { Oauth } from '../../util';
|
import { Oauth } from '../../util';
|
||||||
|
|
||||||
|
const stickyImage = require('../../assets/sticky.gif');
|
||||||
|
|
||||||
interface Props extends RouteComponentProps<any> {
|
interface Props extends RouteComponentProps<any> {
|
||||||
userStore: UserStore;
|
userStore: UserStore;
|
||||||
}
|
}
|
||||||
@@ -40,10 +43,15 @@ export class Forum extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getThreads(categoryId: string) {
|
private async getThreads(categoryId: string) {
|
||||||
const threads = await ThreadService.getCategoryThreads(categoryId);
|
let threads = await ThreadService.getCategoryThreads(categoryId);
|
||||||
|
threads = this.orderBy(threads);
|
||||||
this.setState({ threads });
|
this.setState({ threads });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private orderBy(threads: ThreadModel[]) {
|
||||||
|
return orderBy(threads, ['sticky', 'updated_at'], ['desc', 'desc']);
|
||||||
|
}
|
||||||
|
|
||||||
onNewTopic() {
|
onNewTopic() {
|
||||||
if (this.props.userStore.user) {
|
if (this.props.userStore.user) {
|
||||||
this.setState({ showEditor: true });
|
this.setState({ showEditor: true });
|
||||||
@@ -94,7 +102,7 @@ export class Forum extends React.Component<Props, State> {
|
|||||||
|
|
||||||
renderCell(content: JSX.Element | string, style: any, center?: boolean, header?: boolean) {
|
renderCell(content: JSX.Element | string, style: any, center?: boolean, header?: boolean) {
|
||||||
let classNames: string = '';
|
let classNames: string = '';
|
||||||
classNames += center && ' forum-cell--center';
|
classNames += center ? ' forum-cell--center': '';
|
||||||
classNames += header ? ' forum-cell--header' : ' forum-cell--body';
|
classNames += header ? ' forum-cell--header' : ' forum-cell--body';
|
||||||
return <div className={`forum-cell flex-1 ${classNames}`} style={style}>{content}</div>;
|
return <div className={`forum-cell flex-1 ${classNames}`} style={style}>{content}</div>;
|
||||||
}
|
}
|
||||||
@@ -102,15 +110,20 @@ export class Forum extends React.Component<Props, State> {
|
|||||||
renderThreadRows() {
|
renderThreadRows() {
|
||||||
const categoryId = this.props.match.params['id'];
|
const categoryId = this.props.match.params['id'];
|
||||||
return this.state.threads.map((thread, index) => {
|
return this.state.threads.map((thread, index) => {
|
||||||
|
const authorBluePost = thread.user.permissions === 'admin' ? 'blue' : '';
|
||||||
|
const lastReplyBluePost = thread.last_reply.permissions === 'admin' ? 'blue' : '';
|
||||||
|
const sticky = thread.sticky ? <img src={stickyImage} title="Sticky"/> : '';
|
||||||
return (
|
return (
|
||||||
<div className={`forum-row ${index % 2 === 0 && 'forum-row--dark'}`} key={index}>
|
<div className={`forum-row ${index % 2 === 0 && 'forum-row--dark'}`} key={index}>
|
||||||
{this.renderCell('flag', { maxWidth: '50px' })}
|
{this.renderCell(sticky, { maxWidth: '50px' }, true)}
|
||||||
{this.renderCell(<Link to={`/f/${categoryId}/${thread.id}`}>{thread.title}</Link>, { minWidth: '200px' })}
|
{this.renderCell(<Link to={`/f/${categoryId}/${thread.id}`}>{thread.title}</Link>, { minWidth: '200px' })}
|
||||||
{this.renderCell(<b>{thread.user.character_name || thread.user.battletag}</b>, { maxWidth: '150px' })}
|
{this.renderCell(<b className={authorBluePost}>{thread.user.character_name || thread.user.battletag}</b>, { maxWidth: '150px' })}
|
||||||
{this.renderCell(<b>{thread.reply_count}</b>, { maxWidth: '150px' }, true)}
|
{this.renderCell(<b>{thread.reply_count}</b>, { maxWidth: '150px' }, true)}
|
||||||
{this.renderCell(<b>{thread.view_count}</b>, { maxWidth: '150px' }, true)}
|
{this.renderCell(<b>{thread.view_count}</b>, { maxWidth: '150px' }, true)}
|
||||||
{this.renderCell(
|
{this.renderCell(
|
||||||
<span>by <b>{thread.last_reply.character_name || thread.last_reply.battletag}</b></span>,
|
<div style={{ fontSize: '8pt' }}>
|
||||||
|
by <b className={lastReplyBluePost}>{thread.last_reply.character_name || thread.last_reply.battletag}</b>
|
||||||
|
</div>,
|
||||||
{ maxWidth: '200px' },
|
{ maxWidth: '200px' },
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './forum/forum';
|
export * from './forum/forum';
|
||||||
|
export * from './login/login';
|
||||||
export * from './home/home';
|
export * from './home/home';
|
||||||
export * from './not-found/not-found';
|
export * from './not-found/not-found';
|
||||||
export * from './oauth/oauth';
|
export * from './oauth/oauth';
|
||||||
|
|||||||
68
client/app/pages/login/login.tsx
Normal file
68
client/app/pages/login/login.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
|
import { ContentContainer } from '../../components';
|
||||||
|
import { UserService } from '../../services';
|
||||||
|
|
||||||
|
interface Props extends RouteComponentProps<any> {}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
errorMessage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Login extends React.Component<Props, State> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async login(event: any) {
|
||||||
|
event.preventDefault();
|
||||||
|
const { username, password } = this.state;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await UserService.login(username, password);
|
||||||
|
window.location.pathname = '/';
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.setState({ errorMessage: 'Invalid login.' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { username, password } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContentContainer>
|
||||||
|
<form onSubmit={e => this.login(e)}>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Username</label>
|
||||||
|
<input
|
||||||
|
autoFocus
|
||||||
|
type="text"
|
||||||
|
className="input"
|
||||||
|
value={username}
|
||||||
|
onChange={event => this.setState({ username: event.target.value })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Password</label>
|
||||||
|
<input type="password" className="input" value={password} onChange={event => this.setState({ password: event.target.value })} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<input className="input__button" type="submit" value="Submit" />
|
||||||
|
<span className="red" style={{ marginLeft: '10px' }}>
|
||||||
|
{this.state.errorMessage}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ContentContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@ export class Thread extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderUserInfo(reply: ReplyModel) {
|
renderUserInfo(reply: ReplyModel) {
|
||||||
const { battletag, character_avatar, character_class, character_guild, character_name, character_realm } = reply.user;
|
const { battletag, character_avatar, character_class, character_guild, character_name, character_realm, permissions } = reply.user;
|
||||||
return (
|
return (
|
||||||
<div className="reply__user-container">
|
<div className="reply__user-container">
|
||||||
<Portrait imageSrc={CharacterService.getAvatar(character_avatar)}/>
|
<Portrait imageSrc={CharacterService.getAvatar(character_avatar)}/>
|
||||||
@@ -93,6 +93,7 @@ export class Thread extends React.Component<Props, State> {
|
|||||||
{character_class && <div><small>{character_class}</small></div>}
|
{character_class && <div><small>{character_class}</small></div>}
|
||||||
{character_guild && <div><small><b>Guild: </b>{character_guild}</small></div>}
|
{character_guild && <div><small><b>Guild: </b>{character_guild}</small></div>}
|
||||||
{character_realm && <div><small><b>Realm: </b>{character_realm}</small></div>}
|
{character_realm && <div><small><b>Realm: </b>{character_realm}</small></div>}
|
||||||
|
{permissions === 'admin' && <div className="blue">Admin Poster</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -101,6 +102,7 @@ export class Thread extends React.Component<Props, State> {
|
|||||||
renderReplies(): any {
|
renderReplies(): any {
|
||||||
return this.state.thread!.replies.map((reply, index) => {
|
return this.state.thread!.replies.map((reply, index) => {
|
||||||
const replyDark = index % 2 === 0 ? 'reply--dark' : '';
|
const replyDark = index % 2 === 0 ? 'reply--dark' : '';
|
||||||
|
const bluePost = reply.user.permissions === 'admin' ? 'blue-post' : '';
|
||||||
return (
|
return (
|
||||||
<div className="reply-container" key={index}>
|
<div className="reply-container" key={index}>
|
||||||
<div className={`reply ${replyDark}`}>
|
<div className={`reply ${replyDark}`}>
|
||||||
@@ -124,7 +126,7 @@ export class Thread extends React.Component<Props, State> {
|
|||||||
|
|
||||||
<div className="reply__content markdown-container">
|
<div className="reply__content markdown-container">
|
||||||
{this.renderQuotedReply(reply)}
|
{this.renderQuotedReply(reply)}
|
||||||
<div dangerouslySetInnerHTML={{ __html: marked(reply.content, { sanitize: true }) }}/>
|
<div className={bluePost} dangerouslySetInnerHTML={{ __html: marked(reply.content, { sanitize: true }) }}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ export class UserAccount extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getCharacters();
|
// only load characters if user is battenet user
|
||||||
|
if (get(this.props, 'userStore.user.access_token')) {
|
||||||
|
this.getCharacters();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectedCharacter(): CharacterModel {
|
private selectedCharacter(): CharacterModel {
|
||||||
@@ -85,43 +88,6 @@ export class UserAccount extends React.Component<Props, State> {
|
|||||||
this.setState({ selectedAvatarIndex });
|
this.setState({ selectedAvatarIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDropDowns() {
|
|
||||||
if (!this.selectedCharacter()) {
|
|
||||||
return <div></div>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h2>Set your default character</h2>
|
|
||||||
<div style={{ margin: '0 10px 10px 0', display: 'inline-block' }}>
|
|
||||||
<select value={this.selectedCharacter().realm}
|
|
||||||
onChange={event => this.onRealmSelect(event)}>
|
|
||||||
{map(this.state.characters, (_, realm: string) => {
|
|
||||||
return <option key={`realm${realm}`}>{realm}</option>;
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
<select style={{ marginLeft: '5px' }}
|
|
||||||
onChange={event => this.onCharSelect(event)}>
|
|
||||||
{map(this.state.characters[this.state.selectedRealm!], (value, index) => {
|
|
||||||
return <option key={this.state.selectedRealm! + index} value={index}>{value.name}</option>;
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a onClick={() => this.onSave()}>Save</a>
|
|
||||||
<div className="avatar-list">
|
|
||||||
{this.selectedCharacter().avatarList!.map((val, index) => {
|
|
||||||
const avatarClass = this.state.selectedAvatarIndex === index ? 'avatar-list__item--selected' : '';
|
|
||||||
return (
|
|
||||||
<div key={index} className={`avatar-list__item ${avatarClass}`} onClick={() => this.onAvatarSelect(index)}>
|
|
||||||
<img src={val.imageSrc}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async onSave() {
|
private async onSave() {
|
||||||
const { name, guild, realm } = this.selectedCharacter();
|
const { name, guild, realm } = this.selectedCharacter();
|
||||||
const selectedAvatar = this.selectedCharacter().avatarList![this.state.selectedAvatarIndex].title;
|
const selectedAvatar = this.selectedCharacter().avatarList![this.state.selectedAvatarIndex].title;
|
||||||
@@ -160,6 +126,43 @@ export class UserAccount extends React.Component<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderDropDowns() {
|
||||||
|
if (!this.selectedCharacter()) {
|
||||||
|
return <div></div>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Set your default character</h2>
|
||||||
|
<div style={{ margin: '0 10px 10px 0', display: 'inline-block' }}>
|
||||||
|
<select value={this.selectedCharacter().realm}
|
||||||
|
onChange={event => this.onRealmSelect(event)}>
|
||||||
|
{map(this.state.characters, (_, realm: string) => {
|
||||||
|
return <option key={`realm${realm}`}>{realm}</option>;
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<select style={{ marginLeft: '5px' }}
|
||||||
|
onChange={event => this.onCharSelect(event)}>
|
||||||
|
{map(this.state.characters[this.state.selectedRealm!], (value, index) => {
|
||||||
|
return <option key={this.state.selectedRealm! + index} value={index}>{value.name}</option>;
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a onClick={() => this.onSave()}>Save</a>
|
||||||
|
<div className="avatar-list">
|
||||||
|
{this.selectedCharacter().avatarList!.map((val, index) => {
|
||||||
|
const avatarClass = this.state.selectedAvatarIndex === index ? 'avatar-list__item--selected' : '';
|
||||||
|
return (
|
||||||
|
<div key={index} className={`avatar-list__item ${avatarClass}`} onClick={() => this.onAvatarSelect(index)}>
|
||||||
|
<img src={val.imageSrc}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
if (this.state.noCharacters) {
|
if (this.state.noCharacters) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
|||||||
import { Provider } from 'mobx-react';
|
import { Provider } from 'mobx-react';
|
||||||
import { initializeAxios } from './axios/axios';
|
import { initializeAxios } from './axios/axios';
|
||||||
import { Footer, Header } from './components';
|
import { Footer, Header } from './components';
|
||||||
import { Forum, Home, NotFound, Oauth, Realms, Thread, UserAccount } from './pages';
|
import { Forum, Home, Login, NotFound, Oauth, Realms, Thread, UserAccount } from './pages';
|
||||||
import { stores } from './stores/stores';
|
import { stores } from './stores/stores';
|
||||||
|
|
||||||
// styling
|
// styling
|
||||||
@@ -48,6 +48,7 @@ export class Routes extends React.Component<Props, State> {
|
|||||||
<Route exact path="/f/:categoryId/:threadId" component={Thread} />
|
<Route exact path="/f/:categoryId/:threadId" component={Thread} />
|
||||||
<Route exact path="/oauth" component={Oauth} />
|
<Route exact path="/oauth" component={Oauth} />
|
||||||
<Route exact path="/user-account" component={UserAccount} />
|
<Route exact path="/user-account" component={UserAccount} />
|
||||||
|
<Route exact path="/login" component={Login} />
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
$fontPrimary: #cccccc;
|
$fontPrimary: #cccccc;
|
||||||
$linkColor: #FFB019;
|
$linkColor: #FFB019;
|
||||||
|
$bluePost: #00C0FF;
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-family: Arial,Helvetica,Sans-Serif;
|
font-family: Arial,Helvetica,Sans-Serif;
|
||||||
@@ -103,6 +104,12 @@ span.grey {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
& + & {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
border: 1px solid lighten(#161616, 10%);
|
border: 1px solid lighten(#161616, 10%);
|
||||||
background-color: #161616;
|
background-color: #161616;
|
||||||
@@ -157,3 +164,17 @@ div {
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blue {
|
||||||
|
color: $bluePost !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue-post {
|
||||||
|
p {
|
||||||
|
color: $bluePost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -151,6 +151,11 @@ const avatarList: AvatarModel[] = [
|
|||||||
title: 'undead_m',
|
title: 'undead_m',
|
||||||
imageSrc: require('../assets/avatars/Undead_male.gif'),
|
imageSrc: require('../assets/avatars/Undead_male.gif'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
raceId: 0,
|
||||||
|
title: 'ordinn',
|
||||||
|
imageSrc: require('../assets/avatars/Ordinn.gif'),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CharacterService = {
|
export const CharacterService = {
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import { orderBy } from 'lodash';
|
|
||||||
import axios from '../axios/axios';
|
import axios from '../axios/axios';
|
||||||
import { ThreadModel } from '../model';
|
import { ThreadModel } from '../model';
|
||||||
|
|
||||||
const getCategoryThreads = async (category_id: string): Promise<ThreadModel[]> => {
|
const getCategoryThreads = async (category_id: string): Promise<ThreadModel[]> => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(`/api/thread?category_id=${category_id}`);
|
const res = await axios.get(`/api/thread?category_id=${category_id}`);
|
||||||
return orderBy(res.data.data as ThreadModel[], (thread: ThreadModel) => {
|
return res.data.data;
|
||||||
return -(new Date(thread.updated_at));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import { CharacterService } from './character.service';
|
|||||||
|
|
||||||
// fetch user and store in local storage
|
// fetch user and store in local storage
|
||||||
const authorize = async (code: string): Promise<void> => {
|
const authorize = async (code: string): Promise<void> => {
|
||||||
try {
|
const res = await axios.post('/api/user/authorize', { code });
|
||||||
const res = await axios.post('/api/user/authorize', { code });
|
userStore.setUser(res.data.data);
|
||||||
userStore.setUser(res.data.data);
|
};
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
const login = async (username: string, password: string): Promise<any> => {
|
||||||
}
|
const res = await axios.post('/api/user/login', { username, password });
|
||||||
|
userStore.setUser(res.data.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCharacters = async (): Promise<any> => {
|
const getCharacters = async (): Promise<any> => {
|
||||||
@@ -53,6 +54,7 @@ const saveCharacter = async (character: any): Promise<any> => {
|
|||||||
|
|
||||||
export const UserService = {
|
export const UserService = {
|
||||||
authorize,
|
authorize,
|
||||||
saveCharacter,
|
|
||||||
getCharacters,
|
getCharacters,
|
||||||
|
login,
|
||||||
|
saveCharacter,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user