diff --git a/src/App.tsx b/src/App.tsx index 1698d1e..e3fdd72 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,15 @@ import { Route, Router } from "@solidjs/router"; import type { Component } from "solid-js"; -import MainView from "./views/MainView/MainView"; -import SettingsView from "./views/SettingsView/SettingsView"; +import { MainView } from "./views/MainView"; +import { SettingsView } from "./views/SettingsView"; +import { LoginView } from "./views/LoginView"; const App: Component = () => { return ( + ); }; diff --git a/src/api/auth/auth.ts b/src/api/auth/auth.ts new file mode 100644 index 0000000..3d06bab --- /dev/null +++ b/src/api/auth/auth.ts @@ -0,0 +1,18 @@ +import { callApi, HTTP } from "../tools"; +import { + IFetchLoginRequest, + IFetchLoginResponse, + IFetchRefreshResponse, +} from "./types"; + +const fetchLoginApi = async ( + request: IFetchLoginRequest, +): Promise => { + return await callApi(HTTP.POST, `auth/login`, request); +}; + +const fetchRefreshApi = async (): Promise => { + return await callApi(HTTP.GET_REFRESH, `auth/refresh`); +}; + +export { fetchLoginApi, fetchRefreshApi }; diff --git a/src/api/auth/index.ts b/src/api/auth/index.ts new file mode 100644 index 0000000..130045b --- /dev/null +++ b/src/api/auth/index.ts @@ -0,0 +1,2 @@ +export * from "./auth"; +export * from "./types"; diff --git a/src/api/auth/types.ts b/src/api/auth/types.ts new file mode 100644 index 0000000..02a0edd --- /dev/null +++ b/src/api/auth/types.ts @@ -0,0 +1,21 @@ +interface IFetchLoginRequest { + username: string; + password: string; +} + +interface IFetchLoginResponse { + id: string; + ownerId: string; +} + +interface IFetchRefreshResponse { + id: string; + ownerId: string; + token: string; +} + +export { + type IFetchLoginRequest, + type IFetchLoginResponse, + type IFetchRefreshResponse, +}; diff --git a/src/api/config.json b/src/api/config.json index 336a8c3..ad4cfd5 100644 --- a/src/api/config.json +++ b/src/api/config.json @@ -1,5 +1,6 @@ { "schema": "http", "url": "localhost", - "port": 3012 + "port": 3012, + "path": "api/v1" } diff --git a/src/api/tools.ts b/src/api/tools.ts index c02c772..d36128d 100644 --- a/src/api/tools.ts +++ b/src/api/tools.ts @@ -1,31 +1,75 @@ +import { state } from "../store/state"; import config from "./config.json"; enum HTTP { + GET_REFRESH, GET, POST, + PATCH, + DELETE, } -async function callApi(type: HTTP, path: string, body?: any) { +async function callApi(type: HTTP, path: string, body?: object) { let response: Response; switch (type) { - case HTTP.GET: + case HTTP.GET_REFRESH: response = await fetch( - `${config.schema}://${config.url}:${config.port}/${path}`, + `${config.schema}://${config.url}:${config.port}/${config.path}/${path}`, { method: "GET", + credentials: "include", headers: { "Content-Type": "application/json", }, }, ); break; + case HTTP.GET: + response = await fetch( + `${config.schema}://${config.url}:${config.port}/${config.path}/${path}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${state.auth.session?.token}`, + }, + }, + ); + break; case HTTP.POST: response = await fetch( - `${config.schema}://${config.url}:${config.port}/${path}`, + `${config.schema}://${config.url}:${config.port}/${config.path}/${path}`, { method: "POST", headers: { "Content-Type": "application/json", + Authorization: `Bearer ${state.auth.session?.token}`, + }, + body: JSON.stringify(body ?? {}), + }, + ); + break; + case HTTP.PATCH: + response = await fetch( + `${config.schema}://${config.url}:${config.port}/${config.path}/${path}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${state.auth.session?.token}`, + }, + body: JSON.stringify(body ?? {}), + }, + ); + break; + case HTTP.DELETE: + response = await fetch( + `${config.schema}://${config.url}:${config.port}/${config.path}/${path}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${state.auth.session?.token}`, }, body: JSON.stringify(body ?? {}), }, diff --git a/src/components/Channel/Channel.tsx b/src/components/Channel/Channel.tsx index 5361823..f8885d6 100644 --- a/src/components/Channel/Channel.tsx +++ b/src/components/Channel/Channel.tsx @@ -4,4 +4,4 @@ const Channel: Component = () => { return
; }; -export default Channel; +export { Channel }; diff --git a/src/components/ChannelBar/ChannelBar.tsx b/src/components/ChannelBar/ChannelBar.tsx index ebbaaf7..bc39db4 100644 --- a/src/components/ChannelBar/ChannelBar.tsx +++ b/src/components/ChannelBar/ChannelBar.tsx @@ -8,4 +8,4 @@ const ChannelBar: Component = () => { ); }; -export default ChannelBar; +export { ChannelBar }; diff --git a/src/components/Community/Community.tsx b/src/components/Community/Community.tsx index 70848ae..4be636c 100644 --- a/src/components/Community/Community.tsx +++ b/src/components/Community/Community.tsx @@ -14,4 +14,4 @@ const Community: Component = (props: ICommunityProps) => { ); }; -export default Community; +export { Community }; diff --git a/src/components/Member/Member.tsx b/src/components/Member/Member.tsx index 8f4510b..e2b7a3f 100644 --- a/src/components/Member/Member.tsx +++ b/src/components/Member/Member.tsx @@ -4,4 +4,4 @@ const Member: Component = () => { return
; }; -export default Member; +export { Member }; diff --git a/src/components/Message/Message.tsx b/src/components/Message/Message.tsx index cfd8d2c..199d166 100644 --- a/src/components/Message/Message.tsx +++ b/src/components/Message/Message.tsx @@ -20,4 +20,4 @@ const Message: Component = (props: IMessageProps) => { ); }; -export default Message; +export { Message }; diff --git a/src/components/MessageBar/MessageBar.tsx b/src/components/MessageBar/MessageBar.tsx index c0da0c2..143efff 100644 --- a/src/components/MessageBar/MessageBar.tsx +++ b/src/components/MessageBar/MessageBar.tsx @@ -1,13 +1,36 @@ import type { Component } from "solid-js"; +import { dispatch } from "../../store/state"; +import { UserActionTypes } from "../../store/user"; +import { AuthActionTypes } from "../../store/auth"; const MessageBar: Component = () => { + const onRefresh = () => { + dispatch({ + type: AuthActionTypes.FETCH_REFRESH_START, + }); + }; + const onSend = () => { + dispatch({ + type: UserActionTypes.FETCH_LOGGED_USER_ID_START, + }); + }; + return (
- +
@@ -15,4 +38,4 @@ const MessageBar: Component = () => { ); }; -export default MessageBar; +export { MessageBar }; diff --git a/src/services/auth/auth.ts b/src/services/auth/auth.ts new file mode 100644 index 0000000..78b1265 --- /dev/null +++ b/src/services/auth/auth.ts @@ -0,0 +1,26 @@ +import { fetchLoginApi, fetchRefreshApi } from "../../api/auth"; +import { AuthActionTypes } from "../../store/auth"; +import { dispatch } from "../../store/state"; + +const fetchLogin = async (username: string, password: string) => { + const data = await fetchLoginApi({ + username: username, + password: password, + }); + + dispatch({ + type: AuthActionTypes.FETCH_LOGIN_FINISH, + payload: data, + }); +}; + +const fetchRefresh = async () => { + const data = await fetchRefreshApi(); + + dispatch({ + type: AuthActionTypes.FETCH_REFRESH_FINISH, + payload: data, + }); +}; + +export { fetchLogin, fetchRefresh }; diff --git a/src/services/auth/index.ts b/src/services/auth/index.ts new file mode 100644 index 0000000..e6801cf --- /dev/null +++ b/src/services/auth/index.ts @@ -0,0 +1 @@ +export * from "./auth"; diff --git a/src/store/actions.ts b/src/store/actions.ts index 3524a2f..bace320 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -1,8 +1,9 @@ +import { AuthActionTypes, AuthAction } from "./auth"; import { UserActionTypes, UserAction } from "./user"; import { CommunityActionTypes, CommunityAction } from "./community"; -type ActionTypes = UserActionTypes | CommunityActionTypes; +type ActionTypes = AuthActionTypes | UserActionTypes | CommunityActionTypes; -type Action = UserAction | CommunityAction; +type Action = AuthAction | UserAction | CommunityAction; export { type Action, type ActionTypes }; diff --git a/src/store/auth/actions.ts b/src/store/auth/actions.ts new file mode 100644 index 0000000..c4db806 --- /dev/null +++ b/src/store/auth/actions.ts @@ -0,0 +1,26 @@ +import { + IFetchLoginRequest, + IFetchLoginResponse, + IFetchRefreshResponse, +} from "../../api/auth"; + +enum AuthActionTypes { + FETCH_LOGIN_START = "FETCH_LOGIN_START", + FETCH_LOGIN_FINISH = "FETCH_LOGIN_FINISH", + FETCH_REFRESH_START = "FETCH_REFRESH_START", + FETCH_REFRESH_FINISH = "FETCH_REFRESH_FINISH", +} + +type AuthAction = + | { type: AuthActionTypes.FETCH_LOGIN_START; payload: IFetchLoginRequest } + | { + type: AuthActionTypes.FETCH_LOGIN_FINISH; + payload: IFetchLoginResponse; + } + | { type: AuthActionTypes.FETCH_REFRESH_START } + | { + type: AuthActionTypes.FETCH_REFRESH_FINISH; + payload: IFetchRefreshResponse; + }; + +export { AuthActionTypes, type AuthAction }; diff --git a/src/store/auth/auth.ts b/src/store/auth/auth.ts new file mode 100644 index 0000000..b304ddb --- /dev/null +++ b/src/store/auth/auth.ts @@ -0,0 +1,28 @@ +import { fetchLogin, fetchRefresh } from "../../services/auth"; +import { AuthActionTypes, AuthAction } from "./actions"; +import { IAuthState } from "./types"; + +function authReducer(state: IAuthState, action: AuthAction): IAuthState { + switch (action.type) { + case AuthActionTypes.FETCH_LOGIN_START: + fetchLogin(action.payload.username, action.payload.password); + return state; + case AuthActionTypes.FETCH_LOGIN_FINISH: + return { + ...state, + session: action.payload, + }; + case AuthActionTypes.FETCH_REFRESH_START: + fetchRefresh(); + return state; + case AuthActionTypes.FETCH_REFRESH_FINISH: + return { + ...state, + session: action.payload, + }; + default: + return state; + } +} + +export { authReducer }; diff --git a/src/store/auth/index.ts b/src/store/auth/index.ts new file mode 100644 index 0000000..f821cc3 --- /dev/null +++ b/src/store/auth/index.ts @@ -0,0 +1,3 @@ +export * from "./auth"; +export * from "./actions"; +export * from "./types"; diff --git a/src/store/auth/types.ts b/src/store/auth/types.ts new file mode 100644 index 0000000..21bd7a5 --- /dev/null +++ b/src/store/auth/types.ts @@ -0,0 +1,11 @@ +interface IAuthState { + session?: ISession; +} + +interface ISession { + id?: string; + ownerId?: string; + token?: string; +} + +export { type IAuthState, type ISession }; diff --git a/src/store/reducers.ts b/src/store/reducers.ts index 30e23d1..4e25f89 100644 --- a/src/store/reducers.ts +++ b/src/store/reducers.ts @@ -1,10 +1,12 @@ import { IState } from "./types"; import { Action } from "./actions"; +import { AuthAction, authReducer } from "./auth"; import { UserAction, userReducer } from "./user"; import { CommunityAction, communityReducer } from "./community"; function reducer(state: IState, action: Action): IState { return { + auth: authReducer(state.auth, action as AuthAction), user: userReducer(state.user, action as UserAction), community: communityReducer(state.community, action as CommunityAction), }; diff --git a/src/store/state.ts b/src/store/state.ts index 13051dc..40a10ef 100644 --- a/src/store/state.ts +++ b/src/store/state.ts @@ -4,6 +4,9 @@ import { Action } from "./actions"; import { reducer } from "./reducers"; const [state, setState] = createStore({ + auth: { + session: undefined, + }, user: { loggedUserId: undefined, users: {}, diff --git a/src/store/types.ts b/src/store/types.ts index 7927a0d..334c00a 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -1,7 +1,9 @@ +import { IAuthState } from "./auth"; import { IUserState } from "./user"; import { ICommunityState } from "./community"; interface IState { + auth: IAuthState; user: IUserState; community: ICommunityState; } diff --git a/src/views/ChannelView/ChannelView.tsx b/src/views/ChannelView/ChannelView.tsx index d7e6c23..5a25313 100644 --- a/src/views/ChannelView/ChannelView.tsx +++ b/src/views/ChannelView/ChannelView.tsx @@ -1,5 +1,5 @@ import type { Component } from "solid-js"; -import CommunityView from "../CommunityView/CommunityView"; +import { CommunityView } from "../CommunityView"; const ChannelView: Component = () => { return ( @@ -10,4 +10,4 @@ const ChannelView: Component = () => { ); }; -export default ChannelView; +export { ChannelView }; diff --git a/src/views/ChatView/ChatView.tsx b/src/views/ChatView/ChatView.tsx index bd1e834..11c1e77 100644 --- a/src/views/ChatView/ChatView.tsx +++ b/src/views/ChatView/ChatView.tsx @@ -1,7 +1,7 @@ import { onMount, type Component } from "solid-js"; -import ChannelBar from "../../components/ChannelBar/ChannelBar"; -import MessageBar from "../../components/MessageBar/MessageBar"; -import Message from "../../components/Message/Message"; +import { ChannelBar } from "../../components/ChannelBar"; +import { MessageBar } from "../../components/MessageBar"; +import { Message } from "../../components/Message"; const ChatView: Component = () => { const testMessages = [ @@ -211,4 +211,4 @@ const ChatView: Component = () => { ); }; -export default ChatView; +export { ChatView }; diff --git a/src/views/CommunityView/CommunityView.tsx b/src/views/CommunityView/CommunityView.tsx index 5f6b8c2..f7f8673 100644 --- a/src/views/CommunityView/CommunityView.tsx +++ b/src/views/CommunityView/CommunityView.tsx @@ -1,5 +1,5 @@ import type { Component } from "solid-js"; -import Community from "../../components/Community/Community"; +import { Community } from "../../components/Community"; const CommunityView: Component = () => { const communitiesTest = [ @@ -35,4 +35,4 @@ const CommunityView: Component = () => { ); }; -export default CommunityView; +export { CommunityView }; diff --git a/src/views/LoginView/LoginView.tsx b/src/views/LoginView/LoginView.tsx index 3247222..3e0c09a 100644 --- a/src/views/LoginView/LoginView.tsx +++ b/src/views/LoginView/LoginView.tsx @@ -1,7 +1,50 @@ -import type { Component } from "solid-js"; +import { createSignal, type Component } from "solid-js"; +import { dispatch } from "../../store/state"; +import { AuthActionTypes } from "../../store/auth"; const LoginView: Component = () => { - return
; + const [getUsername, setUsername] = createSignal(""); + const [getPassword, setPassword] = createSignal(""); + + const onLogin = () => { + dispatch({ + type: AuthActionTypes.FETCH_LOGIN_START, + payload: { + username: getUsername(), + password: getPassword(), + }, + }); + }; + + return ( +
+
+ Login + + + setUsername(e.target.value)} + /> + + + setPassword(e.target.value)} + /> + + +
+
+ ); }; -export default LoginView; +export { LoginView }; diff --git a/src/views/MainView/MainView.tsx b/src/views/MainView/MainView.tsx index 410f5a5..b4e764d 100644 --- a/src/views/MainView/MainView.tsx +++ b/src/views/MainView/MainView.tsx @@ -1,7 +1,7 @@ import type { Component } from "solid-js"; -import ChannelView from "../ChannelView/ChannelView"; -import ChatView from "../ChatView/ChatView"; -import MemberView from "../MemberView/MemberView"; +import { ChannelView } from "../ChannelView"; +import { ChatView } from "../ChatView"; +import { MemberView } from "../MemberView"; const MainView: Component = () => { return ( @@ -13,4 +13,4 @@ const MainView: Component = () => { ); }; -export default MainView; +export { MainView }; diff --git a/src/views/MemberView/MemberView.tsx b/src/views/MemberView/MemberView.tsx index fec11c3..e80b9a5 100644 --- a/src/views/MemberView/MemberView.tsx +++ b/src/views/MemberView/MemberView.tsx @@ -4,4 +4,4 @@ const MemberView: Component = () => { return
; }; -export default MemberView; +export { MemberView }; diff --git a/src/views/RegisterView/RegisterView.tsx b/src/views/RegisterView/RegisterView.tsx index 4a202c0..ddba295 100644 --- a/src/views/RegisterView/RegisterView.tsx +++ b/src/views/RegisterView/RegisterView.tsx @@ -4,4 +4,4 @@ const RegisterView: Component = () => { return
; }; -export default RegisterView; +export { RegisterView }; diff --git a/src/views/SettingsView/SettingsView.tsx b/src/views/SettingsView/SettingsView.tsx index ead0300..2cbe33f 100644 --- a/src/views/SettingsView/SettingsView.tsx +++ b/src/views/SettingsView/SettingsView.tsx @@ -4,4 +4,4 @@ const SettingsView: Component = () => { return
; }; -export default SettingsView; +export { SettingsView };