Skip to content

Commit

Permalink
Merge pull request #102 from georgejkaye/login-box
Browse files Browse the repository at this point in the history
Change login box to combined login and settings page
  • Loading branch information
georgejkaye authored Feb 20, 2024
2 parents f496ba9 + 5b5dca3 commit 1fcca4c
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 57 deletions.
6 changes: 5 additions & 1 deletion api/src/cookiebreaks/api/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from fastapi import FastAPI

from cookiebreaks.api.routers import users, breaks, claims, debug
from cookiebreaks.api.routers import data, users, breaks, claims, debug, settings
from cookiebreaks.core.env import get_env_path, get_env_variable, load_envs

tags_metadata = [
{"name": "users", "description": "Authenticate users"},
{"name": "data", "description": "Get cookie break data"},
{"name": "settings", "description": "View and modify cookie break settings"},
{"name": "breaks", "description": "Operations for interacting with cookie breaks"},
{
"name": "claims",
Expand All @@ -30,6 +32,8 @@
)

app.include_router(users.router)
app.include_router(data.router)
app.include_router(settings.router)
app.include_router(breaks.router)
app.include_router(claims.router)
app.include_router(debug.router)
Expand Down
32 changes: 32 additions & 0 deletions api/src/cookiebreaks/api/routers/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from dataclasses import dataclass
from typing import Annotated
from cookiebreaks.api.routers.users import get_current_user
from cookiebreaks.api.routers.utils import (
BreakExternal,
ClaimExternal,
get_breaks,
get_claims,
)
from cookiebreaks.core.database import select_settings
from cookiebreaks.core.structs import Settings, User
from fastapi import APIRouter, Depends


router = APIRouter(prefix="/data", tags=["data"])


@dataclass
class Data:
settings: Settings
breaks: list[BreakExternal]
claims: list[ClaimExternal]


@router.get("", response_model=Data, summary="Get all data")
def get_settings(
current_user: Annotated[User, Depends(get_current_user)],
):
settings = select_settings()
breaks = get_breaks(current_user=current_user)
claims = get_claims(current_user=current_user)
return Data(settings, breaks, claims)
27 changes: 27 additions & 0 deletions api/src/cookiebreaks/api/routers/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from datetime import time
from decimal import Decimal
from typing import Annotated, Optional
from cookiebreaks.api.routers.users import is_admin
from cookiebreaks.core.database import select_settings
from cookiebreaks.core.structs import Settings, User
from fastapi import APIRouter, Depends


router = APIRouter(prefix="/settings", tags=["settings"])


@router.get("", response_model=Settings, summary="Get settings")
def get_settings():
settings = select_settings()
return settings


@router.post("", response_model=Settings, summary="Update settings")
def post_settings(
user: Annotated[User, Depends(is_admin)],
day: int,
time: time,
budget: Decimal,
location: str,
):
set_settings(day, time, budget, location)
31 changes: 31 additions & 0 deletions api/src/cookiebreaks/core/database.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import time
from decimal import Decimal
from unittest.util import strclass
import arrow
Expand All @@ -12,6 +13,7 @@
Claim,
ClaimFilters,
Arrow,
Settings,
User,
)

Expand All @@ -32,6 +34,35 @@ def disconnect(conn: Any, cur: Any) -> None:
cur.close()


def select_settings() -> Settings:
(conn, cur) = connect()
statement = """
SELECT day, time, location, budget
FROM Settings
"""
cur.execute(statement)
(day, time, location, budget) = cur.fetchall()[0]
conn.close()
return Settings(day, time, location, budget)


def set_settings(day: int, time: time, location: str, budget: Decimal):
(conn, cur) = connect()
statement = """
UPDATE Settings
SET
day = %(day)s,
time = %(time)s,
location = %(location)s,
budget = %(budget)s
"""
cur.execute(
statement, {"day": day, "time": time, "location": location, "budget": budget}
)
conn.commit()
conn.close()


def get_user(username: str) -> Optional[User]:
(conn, cur) = connect()
statement = """
Expand Down
9 changes: 9 additions & 0 deletions api/src/cookiebreaks/core/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
from decimal import Decimal
from typing import Literal, Optional
from arrow import Arrow
from datetime import time


@dataclass
class Settings:
day: int
time: time
location: str
budget: Decimal


@dataclass
Expand Down
56 changes: 52 additions & 4 deletions client/src/app/api.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import axios from "axios"
import { Claim, CookieBreak, UpdateFn, User } from "./structs"
import {
Claim,
CookieBreak,
Day,
Settings,
UpdateFn,
User,
dayNumberToDay,
dayToDayNumber,
} from "./structs"
import { Data, SetState } from "./page"

const dateOrUndefined = (datetime: string | undefined) =>
datetime ? new Date(datetime) : undefined

const responseToSettings = (set: any) => ({
day: dayNumberToDay(set.day),
time: new Date(`1970-01-01T${set.time}`),
location: set.location,
budget: Number.parseFloat(set.budget),
})

const responseToBreak = (b: any) => ({
id: b.id,
host: b.host,
Expand Down Expand Up @@ -71,11 +87,13 @@ export const login = async (
)
setBreaks(breakObjects)
setClaims(claimObjects)
setTimeout(() => setLoading(false), 1)
return 0
} catch (err) {
console.log(err)
setStatus("Could not log in...")
} finally {
setTimeout(() => setLoading(false), 1)
return 1
}
}
}
Expand All @@ -84,16 +102,46 @@ export const getData = async (
user: User | undefined,
setBreaks: SetState<CookieBreak[]>,
setClaims: SetState<Claim[]>,
setSettings: SetState<Settings | undefined>,
setLoadingData: SetState<boolean>
) => {
setLoadingData(true)
let breaks = await getBreaks(user)
let claims = await getClaims(user, breaks)
let endpoint = `/api/data`
let config = {
headers: getHeaders(user),
}
let response = await axios.get(endpoint, config)
let data = response.data
let settings = responseToSettings(data.settings)
let breaks = data.breaks.map(responseToBreak)
let claims = data.claims.map(responseToClaim)
setSettings(settings)
setBreaks(breaks)
setClaims(claims)
setTimeout(() => setLoadingData(false))
}

export const postSettings = async (
user: User | undefined,
day: Day,
time: Date,
location: string,
budget: number
) => {
let endpoint = `/api/settings`
let config = {
params: {
day: dayToDayNumber(day),
time: time.toTimeString().substring(0, 5),
location: location,
budget: budget,
},
headers: getHeaders(user),
}
let response = await axios.get(endpoint, config)
return response.status
}

export const getBreaks = async (user: User | undefined) => {
let endpoint = `/api/breaks`
let config = {
Expand Down
34 changes: 29 additions & 5 deletions client/src/app/bar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { Dispatch, SetStateAction, useState } from "react"
import { User, CookieBreak, Claim } from "./structs"
import { User, CookieBreak, Claim, Settings } from "./structs"
import Loader from "./loader"
import { getData, login } from "./api"
import { LoginModal, LogoutModal } from "./modals/login"
import { Data, SetState } from "./page"
import { Data, Mode, SetState } from "./page"

const InputBox = (props: {
type: string
Expand All @@ -30,6 +30,8 @@ const LoginButton = (props: {
setClaims: SetState<Claim[]>
setLoadingLogin: SetState<boolean>
user: User | undefined
mode: Mode
setMode: SetState<Mode>
}) => {
const [isActive, setActive] = useState(false)
const [userText, setUserText] = useState("")
Expand All @@ -54,9 +56,13 @@ const LoginButton = (props: {
<>
<div
className="hover:underline cursor-pointer px-2"
onClick={toggleLoginButton}
onClick={(e) =>
props.mode === Mode.Main
? props.setMode(Mode.Admin)
: props.setMode(Mode.Main)
}
>
{!props.user ? "Login" : props.user.user}
{!props.user ? "Login" : "Settings"}
</div>
{!props.user ? (
<LoginModal
Expand Down Expand Up @@ -85,6 +91,8 @@ const LoginRegion = (props: {
setBreaks: SetState<CookieBreak[]>
setClaims: SetState<Claim[]>
user: User | undefined
mode: Mode
setMode: SetState<Mode>
}) => {
const [isLoadingLogin, setLoadingLogin] = useState(false)
return (
Expand All @@ -98,6 +106,8 @@ const LoginRegion = (props: {
setClaims={props.setClaims}
setUser={props.setUser}
setLoadingLogin={setLoadingLogin}
mode={props.mode}
setMode={props.setMode}
/>
)}
</div>
Expand All @@ -108,13 +118,15 @@ const RefreshButton = (props: {
user: User | undefined
setBreaks: SetState<CookieBreak[]>
setClaims: SetState<Claim[]>
setSettings: SetState<Settings | undefined>
setLoadingData: SetState<boolean>
}) => {
const onClickRefresh = (e: React.MouseEvent<HTMLButtonElement>) =>
getData(
props.user,
props.setBreaks,
props.setClaims,
props.setSettings,
props.setLoadingData
)
return <button onClick={onClickRefresh}>Refresh</button>
Expand All @@ -124,22 +136,28 @@ const RightButtons = (props: {
setUser: SetState<User | undefined>
setBreaks: SetState<CookieBreak[]>
setClaims: SetState<Claim[]>
setSettings: SetState<Settings | undefined>
setLoadingData: SetState<boolean>
user: User | undefined
mode: Mode
setMode: SetState<Mode>
}) => {
return (
<div className="ml-auto flex flex-row">
<div className="ml-auto flex flex-row gap-5">
<RefreshButton
user={props.user}
setBreaks={props.setBreaks}
setClaims={props.setClaims}
setSettings={props.setSettings}
setLoadingData={props.setLoadingData}
/>
<LoginRegion
user={props.user}
setBreaks={props.setBreaks}
setClaims={props.setClaims}
setUser={props.setUser}
mode={props.mode}
setMode={props.setMode}
/>
</div>
)
Expand All @@ -149,8 +167,11 @@ export const TopBar = (props: {
setUser: SetState<User | undefined>
setBreaks: SetState<CookieBreak[]>
setClaims: SetState<Claim[]>
setSettings: SetState<Settings | undefined>
setLoadingData: SetState<boolean>
user: User | undefined
mode: Mode
setMode: SetState<Mode>
}) => {
return (
<div className="flex items-center h-10 p-4 pr-2 bg-bg2 text-fg2">
Expand All @@ -159,8 +180,11 @@ export const TopBar = (props: {
user={props.user}
setBreaks={props.setBreaks}
setClaims={props.setClaims}
setSettings={props.setSettings}
setLoadingData={props.setLoadingData}
setUser={props.setUser}
mode={props.mode}
setMode={props.setMode}
/>
</div>
)
Expand Down
Loading

0 comments on commit 1fcca4c

Please sign in to comment.