Skip to content

Commit

Permalink
Merge partial file
Browse files Browse the repository at this point in the history
  • Loading branch information
xdzqyyds committed Dec 6, 2024
1 parent 1b81f48 commit b5dcd8a
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 169 deletions.
79 changes: 0 additions & 79 deletions server/api/v1/invite.go

This file was deleted.

130 changes: 124 additions & 6 deletions server/api/v1/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package v1
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"woom/server/model"

"github.com/go-chi/render"

"woom/server/model"
"github.com/redis/go-redis/v9"
)

// Login related structs
type LoginRequest struct {
UserId string `json:"userId"`
Password string `json:"password"`
Expand All @@ -21,17 +23,38 @@ type LoginResponse struct {
Message string `json:"message"`
}

// Invite related structs
type InviteRequest struct {
MeetingId string `json:"meetingId"`
InviterId string `json:"inviterId"`
InviteeId string `json:"inviteeId"`
}

type InviteResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
}

type GetInvitationRequest struct {
InviteeId string `json:"inviteeId"`
}

// UserList related structs
type UpdateUserStatusRequest struct {
UserID string `json:"userId"`
Status string `json:"status"`
}

// Login handler
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
var loginReq LoginRequest

// Decode JSON request body
if err := json.NewDecoder(r.Body).Decode(&loginReq); err != nil {
w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, LoginResponse{Success: false, Message: "Invalid request"})
return
}

// get password
ctx := context.Background()
passwordKey := loginReq.UserId
password, err := h.rdb.HGet(ctx, model.UserStorageKey, passwordKey).Result()
Expand All @@ -42,14 +65,12 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
return
}

// verify password
if password != loginReq.Password {
w.WriteHeader(http.StatusUnauthorized)
render.JSON(w, r, LoginResponse{Success: false, Message: "Invalid password"})
return
}

// Update user online status to true
if err := h.rdb.HSet(ctx, model.UserOnlineStatusKey, passwordKey, true).Err(); err != nil {
w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, LoginResponse{Success: false, Message: "Failed to update online status"})
Expand All @@ -58,3 +79,100 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {

render.JSON(w, r, LoginResponse{Success: true, Message: "Login successful"})
}

// Invite handlers
func (h *Handler) Invite(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var inviteData InviteRequest
if err := json.NewDecoder(r.Body).Decode(&inviteData); err != nil {
http.Error(w, "Invalid request payload", http.StatusBadRequest)
return
}

inviteValue := fmt.Sprintf("%s %s", inviteData.MeetingId, inviteData.InviterId)
err := h.rdb.HSet(ctx, model.InvitationKey, inviteData.InviteeId, inviteValue).Err()
if err != nil {
log.Printf("Failed to save invitation for user %s: %v", inviteData.InviteeId, err)
http.Error(w, "Failed to store invitation", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
response := InviteResponse{
Success: true,
Message: "Invitation sent successfully",
}
if err := json.NewEncoder(w).Encode(response); err != nil {
log.Printf("Failed to encode response: %v", err)
http.Error(w, "Failed to send response", http.StatusInternalServerError)
}
}

func (h *Handler) GetInvitation(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var reqBody GetInvitationRequest
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
w.Header().Set("Content-Type", "application/json")
http.Error(w, `{"error": "Invalid request body"}`, http.StatusBadRequest)
return
}

value, err := h.rdb.HGet(ctx, model.InvitationKey, reqBody.InviteeId).Result()
if err == redis.Nil {
// 没有找到邀请,返回空结果但要确保返回正确的 JSON 格式
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"value": nil,
})
return
} else if err != nil {
w.Header().Set("Content-Type", "application/json")
http.Error(w, `{"error": "Internal server error"}`, http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(map[string]string{"value": value}); err != nil {
http.Error(w, `{"error": "Failed to encode response"}`, http.StatusInternalServerError)
return
}

if err := h.rdb.HDel(ctx, model.InvitationKey, reqBody.InviteeId).Err(); err != nil {
log.Printf("Failed to delete inviteeId %s from invitation: %v\n", reqBody.InviteeId, err)
}
}

// UserList handlers
func (h *Handler) UserList(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
onlineStatus, err := h.rdb.HGetAll(ctx, model.UserOnlineStatusKey).Result()
if err != nil {
http.Error(w, "Failed to get user online status", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(onlineStatus); err != nil {
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
}
}

func (h *Handler) UpdateUserList(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

var requestData UpdateUserStatusRequest
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
http.Error(w, "Invalid input data", http.StatusBadRequest)
return
}

err := h.rdb.HSet(ctx, model.UserOnlineStatusKey, requestData.UserID, requestData.Status).Err()
if err != nil {
http.Error(w, "Failed to update user status", http.StatusInternalServerError)
return
}
}
41 changes: 0 additions & 41 deletions server/api/v1/userlist.go

This file was deleted.

2 changes: 1 addition & 1 deletion webapp/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useAtom } from 'jotai'
import Welcome from './pages/welcome'
import Meeting from './pages/meeting'
import { meetingIdAtom, isLoggedInAtom } from './store/atom'
import UserList from './components/userlist'
import UserList from './components/login/userlist'

export default function WOOM() {
const [meetingId] = useAtom(meetingIdAtom)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { sendInvite } from '../lib/api'
import { sendInvite } from '../../lib/api'

interface InviteProps {
meetingId: string;
Expand All @@ -10,18 +10,14 @@ interface InviteProps {
export default function Invite({ meetingId, inviterId, inviteeId }: InviteProps) {
const [isInvited, setIsInvited] = useState<boolean>(false)

const handleInvite = async () => {
try {
const response = await sendInvite(meetingId, inviterId, inviteeId)
if (response.success) {
setIsInvited(true)
console.log('Invite sent successfully')
} else {
console.error('Failed to send invite')
}
} catch (error) {
console.error('Error sending invite:', error)
}
const handleInvite = () => {
sendInvite(meetingId, inviterId, inviteeId)
.catch((error) => {
// 错误捕获
console.error('Error sending invite:', error)
})
setIsInvited(true) // 假设邀请发送后立即更新状态
console.log('Invite sent successfully')
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react'
import { useAtom } from 'jotai'
import { userIdAtom, userPasswordAtom, isLoggedInAtom } from '../store/atom'
import { getLoginStatus } from '../components/join'
import { login } from '../lib/api'
import { setStorage, getStorage } from '../lib/storage'
import { userIdAtom, userPasswordAtom, isLoggedInAtom } from '../../store/atom'
import { getLoginStatus } from '../../components/join'
import { login } from '../../lib/api'
import { setStorage, getStorage } from '../../lib/storage'

export default function Login() {
const [userId, setUserId] = useAtom(userIdAtom)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useEffect, useState } from 'react'
import { useAtom } from 'jotai'
import { getUserOnlineStatus, updateUserStatus } from '../lib/api'
import { getStorage } from '../lib/storage'
import { meetingIdAtom } from '../store/atom'
import { getUserOnlineStatus, updateUserStatus } from '../../lib/api'
import { getStorage } from '../../lib/storage'
import { meetingIdAtom } from '../../store/atom'
import Invite from './Invite'

export default function UserList() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState, useEffect } from 'react'
import { getInvitation } from '../lib/api'
import { setStorageMeeting } from '../lib/storage'
import { getInvitation } from '../../lib/api'
import { setStorageMeeting } from '../../lib/storage'
import { useAtom } from 'jotai'
import { locationAtom, meetingIdAtom } from '../store/atom'
import { locationAtom, meetingIdAtom } from '../../store/atom'

interface InviteWindowProps {
inviteeId: string
Expand All @@ -21,14 +21,11 @@ export default function InviteWindow({ inviteeId }: InviteWindowProps) {
const checkInvitation = async () => {
try {
const value = await getInvitation(inviteeId)
console.log('checkInvitation', value)
if (value) {
setInvitation(value)
setIsOpen(true)
}
} catch (error) {
console.error('Failed to check invitation:', error)
}
} catch {/* empty */ }
}

useEffect(() => {
Expand Down
Loading

0 comments on commit b5dcd8a

Please sign in to comment.