bit of work on friends

This commit is contained in:
Mikayla Dobson
2023-02-13 19:25:28 -06:00
parent 7bd29e4dba
commit fc1046bad5
7 changed files with 129 additions and 28 deletions

View File

@@ -22,6 +22,7 @@ import GroceryListCollection from './components/pages/GroceryListCollection';
import { TokenType } from './util/types'; import { TokenType } from './util/types';
import './sass/App.scss'; import './sass/App.scss';
import handleToken from './util/handleToken'; import handleToken from './util/handleToken';
import AddFriends from './components/pages/AddFriends';
function App() { function App() {
const { setUser, token, setToken } = useAuthContext(); const { setUser, token, setToken } = useAuthContext();
@@ -54,6 +55,7 @@ function App() {
<Route path="/profile" element={<Profile />} /> <Route path="/profile" element={<Profile />} />
<Route path="/collections" element={<CollectionBrowser />} /> <Route path="/collections" element={<CollectionBrowser />} />
<Route path="/collections/:id" element={<Collection />} /> <Route path="/collections/:id" element={<Collection />} />
<Route path="/add-friends" element={<AddFriends />} />
<Route path="/explore" element={<Browser header="" searchFunction={() => {}} />} /> <Route path="/explore" element={<Browser header="" searchFunction={() => {}} />} />
<Route path="/recipe/:id" element={<Recipe />} /> <Route path="/recipe/:id" element={<Recipe />} />
<Route path="/subscriptions" element={<Subscriptions />} /> <Route path="/subscriptions" element={<Subscriptions />} />

View File

@@ -0,0 +1,22 @@
import Protect from "../../util/Protect"
import { Divider, Panel } from "../ui"
import FriendSearchWidget from "../ui/Widgets/NewFriendWidget"
const AddFriends = () => {
return (
<Protect>
<h1>Search for New Friends</h1>
<Divider />
<Panel>
<h2>Use the widget below to search for new friends!</h2>
<Divider />
<FriendSearchWidget />
</Panel>
</Protect>
)
}
export default AddFriends

View File

@@ -55,6 +55,7 @@ const LoggedIn = () => {
dropdownActive && ( dropdownActive && (
<Dropdown extraStyles="top-menu-bar actions-bar"> <Dropdown extraStyles="top-menu-bar actions-bar">
<Button onClick={() => handleOptionSelect('/add-recipe')}>Add a Recipe</Button> <Button onClick={() => handleOptionSelect('/add-recipe')}>Add a Recipe</Button>
<Button onClick={() => handleOptionSelect("/add-friends")}>Add Friends</Button>
<Button onClick={() => handleOptionSelect('/collections')}>My Collections</Button> <Button onClick={() => handleOptionSelect('/collections')}>My Collections</Button>
<Button onClick={() => handleOptionSelect('/subscriptions')}>Subscriptions</Button> <Button onClick={() => handleOptionSelect('/subscriptions')}>Subscriptions</Button>
<Button onClick={() => handleOptionSelect('/profile')}>Profile</Button> <Button onClick={() => handleOptionSelect('/profile')}>Profile</Button>

View File

@@ -1,31 +1,38 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { addFriend, getPendingFriendRequests } from "../../util/apiUtils"; import { useAuthContext } from "../../context/AuthContext";
import API from "../../util/API";
// import { addFriend, getPendingFriendRequests } from "../../util/apiUtils";
import { UserCardType } from "../../util/types"; import { UserCardType } from "../../util/types";
import Button from "./Button"; import Button from "./Button";
import Card from "./Card"; import Card from "./Card";
const UserCard: UserCardType = ({ extraStyles, user, canAdd = false, liftData }) => { const UserCard: UserCardType = ({ extraStyles, user }) => {
const [shouldDisable, setShouldDisable] = useState<boolean>(canAdd); const { token } = useAuthContext();
useEffect(() => { useEffect(() => {
if (!token) return;
(async function() { (async function() {
const requestsOpen = await getPendingFriendRequests(); const friends = new API.Friendship(token);
const requestsOpen = await friends.getPendingFriendRequests();
console.log(requestsOpen);
if (!requestsOpen) return; if (!requestsOpen) return;
for (let req of requestsOpen) { for (let req of requestsOpen) {
if (req.targetid == user.id) { if (req.targetid == user.id) {
setShouldDisable(true); console.log('should disable');
return; return;
} }
} }
setShouldDisable(false); console.log('should not disable');
})(); });
}, []) }, [])
const handleClick = async () => { const handleClick = async () => {
const { id } = user; if (!token) return;
const request = await addFriend(id!.toString()); const friends = new API.Friendship(token);
const request = await friends.addFriend(user.id!.toString());
if (request) console.log("Friend request sent to " + user.firstname); if (request) console.log("Friend request sent to " + user.firstname);
} }
@@ -34,7 +41,7 @@ const UserCard: UserCardType = ({ extraStyles, user, canAdd = false, liftData })
<div className="avatar"></div> <div className="avatar"></div>
<h3>{user.firstname} {user.lastname.substring(0,1)}.</h3> <h3>{user.firstname} {user.lastname.substring(0,1)}.</h3>
<h4>@{user.handle}</h4> <h4>@{user.handle}</h4>
{ canAdd && <Button disabledText={"Request Sent"} disabled={shouldDisable} onClick={handleClick}>Add Me</Button> } <Button disabledText={"Request Sent"} onClick={handleClick}>Add Me</Button>
</Card> </Card>
) )
} }

View File

@@ -0,0 +1,60 @@
import { ChangeEvent, FC, useCallback, useEffect, useState } from "react";
import { IUser } from "../../../schemas";
import { TextField, UserCard } from "..";
import { v4 } from "uuid";
import API from "../../../util/API";
import { useAuthContext } from "../../../context/AuthContext";
const FriendSearchWidget: FC<{}> = () => {
const { token } = useAuthContext();
const [searchTerm, setSearchTerm] = useState<string>();
const [userPool, setUserPool] = useState<IUser[]>([]);
const [pendingRequests, setPendingRequests] = useState();
const [friendResults, setFriendResults] = useState<IUser[]>([]);
// load available user pool on mount
useEffect(() => {
if (!token) return;
(async function() {
const users = new API.User(token);
const result = await users.getAll();
if (result) setUserPool(result);
})();
(async function() {
const friends = new API.Friendship(token);
const result = await friends.getAll();
setFriendResults(result);
})();
}, [])
useEffect(() => {
console.log(searchTerm);
searchTerm && setUserPool((prev) => {
const newPool = prev.filter(person => {
if (person.firstname.toLowerCase().includes(searchTerm) || person.lastname.toLowerCase().includes(searchTerm) || person.handle.toLowerCase().includes(searchTerm)) return person;
})
return newPool;
})
}, [searchTerm])
useEffect(() => {
console.log(userPool);
}, [userPool])
return (
<div id="friend-search-widget">
<TextField onChange={(e: ChangeEvent<HTMLInputElement>) => setSearchTerm(e.target.value.toLowerCase())} placeholder={'Search'} />
{
userPool.map((friend: IUser) => {
return <UserCard key={v4()} user={friend} canAdd liftData={() => {}} />
})
}
</div>
)
}
export default FriendSearchWidget;

View File

@@ -1,4 +1,4 @@
import { AxiosHeaders, AxiosRequestHeaders, AxiosResponse } from "axios"; import { AxiosError, AxiosHeaders, AxiosRequestHeaders, AxiosResponse } from "axios";
import { IUser, IUserAuth, IFriendship, IRecipe, IIngredient, ICollection, IGroceryList } from "../schemas"; import { IUser, IUserAuth, IFriendship, IRecipe, IIngredient, ICollection, IGroceryList } from "../schemas";
import { default as _instance } from "./axiosInstance"; import { default as _instance } from "./axiosInstance";
@@ -138,13 +138,31 @@ module API {
export class Friendship extends RestController<IFriendship> { export class Friendship extends RestController<IFriendship> {
constructor(token: string) { constructor(token: string) {
super(Settings.getAPISTRING() + "/app/friends", token); super(Settings.getAPISTRING() + "/app/friend", token);
}
override async getAll() {
try {
const response = await this.instance.get(this.endpoint, this.headers);
return Promise.resolve(response.data);
} catch(e) {
const error = e as AxiosError;
if (error.response?.status == 404) {
console.log('no friends found');
return [];
}
}
} }
async getPendingFriendRequests() { async getPendingFriendRequests() {
const response = await this.instance.get(this.endpoint + "?pending=true", this.headers); const response = await this.instance.get(this.endpoint + "?pending=true", this.headers);
return Promise.resolve(response.data); return Promise.resolve(response.data);
} }
async addFriend(id: string | number) {
const response = await this.instance.post(this.endpoint + `/${id}`, this.headers);
return Promise.resolve(response.data);
}
} }
export class Recipe extends RestController<IRecipe> { export class Recipe extends RestController<IRecipe> {

View File

@@ -9,19 +9,8 @@ const router = Router();
export const friendRouter = (app: Express) => { export const friendRouter = (app: Express) => {
app.use('/app/friend', router); app.use('/app/friend', router);
router.use((req, res, next) => {
let test = req.session.user;
if (req.session.user == undefined) {
throw new Error("No session found");
} else {
const narrowed = req.session.user;
next();
}
})
router.post('/:targetid', restrictAccess, async (req, res, next) => { router.post('/:targetid', restrictAccess, async (req, res, next) => {
const user = req.session.user as IUser; const user = req.user as IUser;
const { targetid } = req.params; const { targetid } = req.params;
try { try {
@@ -34,7 +23,7 @@ export const friendRouter = (app: Express) => {
// get all friendships for a user // get all friendships for a user
router.get('/', async (req, res, next) => { router.get('/', async (req, res, next) => {
const user = req.session.user as IUser; const user = req.user as IUser;
const { pending } = req.query; const { pending } = req.query;
try { try {
@@ -53,7 +42,7 @@ export const friendRouter = (app: Express) => {
// get one friendship by its id // get one friendship by its id
router.get('/:id', async (req, res, next) => { router.get('/:id', async (req, res, next) => {
const { id } = req.params; const { id } = req.params;
const user = req.session.user as IUser; const user = req.user as IUser;
try { try {
const { code, data } = await UserInstance.getFriendshipByID(id, user.id as number); const { code, data } = await UserInstance.getFriendshipByID(id, user.id as number);
@@ -76,7 +65,7 @@ export const friendRouter = (app: Express) => {
router.put('/:id', async (req, res, next) => { router.put('/:id', async (req, res, next) => {
const data = req.body; const data = req.body;
const { id } = req.params; const { id } = req.params;
const user = req.session.user as IUser; const user = req.user as IUser;
try { try {
const response = await UserInstance.updateFriendship(id, user.id as number, data); const response = await UserInstance.updateFriendship(id, user.id as number, data);
@@ -85,4 +74,6 @@ export const friendRouter = (app: Express) => {
next(e); next(e);
} }
}) })
return router;
} }