Code cleanup

This commit is contained in:
Tobias Hopp 2025-04-16 10:19:34 +02:00
parent 3fd311e312
commit ad3ced0650
13 changed files with 106 additions and 104 deletions

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom';
import { AuthProvider, useAuth } from './context/AuthContext'; import { AuthProvider, useAuth } from './context/AuthContext';
import { NetworkProvider } from './context/NetworkContext'; import { NetworkProvider } from './context/NetworkContext';
import Login from './components/auth/Login'; import Login from './components/auth/Login';

View File

@ -44,7 +44,7 @@ export const getUserNetworks = async (): Promise<Network[]> => {
export const createNetwork = async (data: CreateNetworkData): Promise<Network> => { export const createNetwork = async (data: CreateNetworkData): Promise<Network> => {
const response = await axios.post<{ success: boolean; data: Network }>( const response = await axios.post<{ success: boolean; data: Network }>(
`${API_URL}/networks`, `${API_URL}/networks`,
data data,
); );
return response.data.data; return response.data.data;
}; };
@ -52,7 +52,7 @@ export const createNetwork = async (data: CreateNetworkData): Promise<Network> =
// Get a specific network // Get a specific network
export const getNetwork = async (id: string): Promise<Network> => { export const getNetwork = async (id: string): Promise<Network> => {
const response = await axios.get<{ success: boolean; data: Network }>( const response = await axios.get<{ success: boolean; data: Network }>(
`${API_URL}/networks/${id}` `${API_URL}/networks/${id}`,
); );
return response.data.data; return response.data.data;
}; };
@ -61,7 +61,7 @@ export const getNetwork = async (id: string): Promise<Network> => {
export const updateNetwork = async (id: string, data: UpdateNetworkData): Promise<Network> => { export const updateNetwork = async (id: string, data: UpdateNetworkData): Promise<Network> => {
const response = await axios.put<{ success: boolean; data: Network }>( const response = await axios.put<{ success: boolean; data: Network }>(
`${API_URL}/networks/${id}`, `${API_URL}/networks/${id}`,
data data,
); );
return response.data.data; return response.data.data;
}; };

View File

@ -44,7 +44,7 @@ export interface UpdatePersonData {
// Get all people in a network // Get all people in a network
export const getPeople = async (networkId: string): Promise<Person[]> => { export const getPeople = async (networkId: string): Promise<Person[]> => {
const response = await axios.get<{ success: boolean; data: Person[] }>( const response = await axios.get<{ success: boolean; data: Person[] }>(
`${API_URL}/networks/${networkId}/people` `${API_URL}/networks/${networkId}/people`,
); );
return response.data.data; return response.data.data;
}; };
@ -53,7 +53,7 @@ export const getPeople = async (networkId: string): Promise<Person[]> => {
export const addPerson = async (networkId: string, data: CreatePersonData): Promise<Person> => { export const addPerson = async (networkId: string, data: CreatePersonData): Promise<Person> => {
const response = await axios.post<{ success: boolean; data: Person }>( const response = await axios.post<{ success: boolean; data: Person }>(
`${API_URL}/networks/${networkId}/people`, `${API_URL}/networks/${networkId}/people`,
data data,
); );
return response.data.data; return response.data.data;
}; };
@ -62,11 +62,11 @@ export const addPerson = async (networkId: string, data: CreatePersonData): Prom
export const updatePerson = async ( export const updatePerson = async (
networkId: string, networkId: string,
personId: string, personId: string,
data: UpdatePersonData data: UpdatePersonData,
): Promise<Person> => { ): Promise<Person> => {
const response = await axios.put<{ success: boolean; data: Person }>( const response = await axios.put<{ success: boolean; data: Person }>(
`${API_URL}/networks/${networkId}/people/${personId}`, `${API_URL}/networks/${networkId}/people/${personId}`,
data data,
); );
return response.data.data; return response.data.data;
}; };

View File

@ -33,7 +33,7 @@ export interface UpdateRelationshipData {
// Get all relationships in a network // Get all relationships in a network
export const getRelationships = async (networkId: string): Promise<Relationship[]> => { export const getRelationships = async (networkId: string): Promise<Relationship[]> => {
const response = await axios.get<{ success: boolean; data: Relationship[] }>( const response = await axios.get<{ success: boolean; data: Relationship[] }>(
`${API_URL}/networks/${networkId}/relationships` `${API_URL}/networks/${networkId}/relationships`,
); );
return response.data.data; return response.data.data;
}; };
@ -41,11 +41,11 @@ export const getRelationships = async (networkId: string): Promise<Relationship[
// Add a relationship to the network // Add a relationship to the network
export const addRelationship = async ( export const addRelationship = async (
networkId: string, networkId: string,
data: CreateRelationshipData data: CreateRelationshipData,
): Promise<Relationship> => { ): Promise<Relationship> => {
const response = await axios.post<{ success: boolean; data: Relationship }>( const response = await axios.post<{ success: boolean; data: Relationship }>(
`${API_URL}/networks/${networkId}/relationships`, `${API_URL}/networks/${networkId}/relationships`,
data data,
); );
return response.data.data; return response.data.data;
}; };
@ -54,11 +54,11 @@ export const addRelationship = async (
export const updateRelationship = async ( export const updateRelationship = async (
networkId: string, networkId: string,
relationshipId: string, relationshipId: string,
data: UpdateRelationshipData data: UpdateRelationshipData,
): Promise<Relationship> => { ): Promise<Relationship> => {
const response = await axios.put<{ success: boolean; data: Relationship }>( const response = await axios.put<{ success: boolean; data: Relationship }>(
`${API_URL}/networks/${networkId}/relationships/${relationshipId}`, `${API_URL}/networks/${networkId}/relationships/${relationshipId}`,
data data,
); );
return response.data.data; return response.data.data;
}; };
@ -66,7 +66,7 @@ export const updateRelationship = async (
// Remove a relationship // Remove a relationship
export const removeRelationship = async ( export const removeRelationship = async (
networkId: string, networkId: string,
relationshipId: string relationshipId: string,
): Promise<void> => { ): Promise<void> => {
await axios.delete(`${API_URL}/networks/${networkId}/relationships/${relationshipId}`); await axios.delete(`${API_URL}/networks/${networkId}/relationships/${relationshipId}`);
}; };

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState, useCallback } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { GraphData } from 'react-force-graph-2d'; import { GraphData } from 'react-force-graph-2d';
// Define types for graph elements // Define types for graph elements

View File

@ -145,7 +145,7 @@ const FriendshipNetwork: React.FC = () => {
refreshNetwork, refreshNetwork,
updatePersonPosition: updatePersonPositionImpl = ( updatePersonPosition: updatePersonPositionImpl = (
id: string, id: string,
position: { x: number; y: number } position: { x: number; y: number },
) => { ) => {
console.warn('updatePersonPosition not implemented'); console.warn('updatePersonPosition not implemented');
return Promise.resolve(); return Promise.resolve();
@ -336,7 +336,7 @@ const FriendshipNetwork: React.FC = () => {
// Filtered people and relationships // Filtered people and relationships
const filteredPeople = people.filter(person => const filteredPeople = people.filter(person =>
`${person.firstName} ${person.lastName}`.toLowerCase().includes(peopleFilter.toLowerCase()) `${person.firstName} ${person.lastName}`.toLowerCase().includes(peopleFilter.toLowerCase()),
); );
const filteredRelationships = relationships.filter(rel => { const filteredRelationships = relationships.filter(rel => {
@ -430,7 +430,7 @@ const FriendshipNetwork: React.FC = () => {
// Create nodes // Create nodes
const graphNodes = people.map(person => { const graphNodes = people.map(person => {
const connectionCount = relationships.filter( const connectionCount = relationships.filter(
r => r.source === person._id || r.target === person._id r => r.source === person._id || r.target === person._id,
).length; ).length;
// Determine if node should be highlighted // Determine if node should be highlighted
@ -439,7 +439,7 @@ const FriendshipNetwork: React.FC = () => {
? relationships.some( ? relationships.some(
r => r =>
(r.source === selectedPersonId && r.target === person._id) || (r.source === selectedPersonId && r.target === person._id) ||
(r.target === selectedPersonId && r.source === person._id) (r.target === selectedPersonId && r.source === person._id),
) )
: false; : false;
@ -540,7 +540,7 @@ const FriendshipNetwork: React.FC = () => {
(r.source === relationship.source && r.target === relationship.target) || (r.source === relationship.source && r.target === relationship.target) ||
(relationship.bidirectional && (relationship.bidirectional &&
r.source === relationship.target && r.source === relationship.target &&
r.target === relationship.source) r.target === relationship.source),
); );
if (existingRelationship) { if (existingRelationship) {
@ -728,7 +728,8 @@ const FriendshipNetwork: React.FC = () => {
return ( return (
<div className="flex justify-center items-center h-screen bg-slate-900"> <div className="flex justify-center items-center h-screen bg-slate-900">
<div className="flex flex-col items-center space-y-4"> <div className="flex flex-col items-center space-y-4">
<div className="w-16 h-16 border-t-4 border-b-4 border-indigo-500 border-solid rounded-full animate-spin"></div> <div
className="w-16 h-16 border-t-4 border-b-4 border-indigo-500 border-solid rounded-full animate-spin"></div>
<p className="text-white text-lg">Loading your network...</p> <p className="text-white text-lg">Loading your network...</p>
</div> </div>
</div> </div>
@ -953,7 +954,7 @@ const FriendshipNetwork: React.FC = () => {
{sortedPeople.length > 0 ? ( {sortedPeople.length > 0 ? (
sortedPeople.map(person => { sortedPeople.map(person => {
const connectionCount = relationships.filter( const connectionCount = relationships.filter(
r => r.source === person._id || r.target === person._id r => r.source === person._id || r.target === person._id,
).length; ).length;
return ( return (
@ -1668,7 +1669,7 @@ const FriendshipNetwork: React.FC = () => {
<h4 className="font-medium text-indigo-400 mb-2">Connections</h4> <h4 className="font-medium text-indigo-400 mb-2">Connections</h4>
<div className="max-h-40 overflow-y-auto space-y-1 bg-slate-900 rounded-lg p-2"> <div className="max-h-40 overflow-y-auto space-y-1 bg-slate-900 rounded-lg p-2">
{relationships.filter( {relationships.filter(
r => r.source === editPerson._id || r.target === editPerson._id r => r.source === editPerson._id || r.target === editPerson._id,
).length > 0 ? ( ).length > 0 ? (
relationships relationships
.filter(r => r.source === editPerson._id || r.target === editPerson._id) .filter(r => r.source === editPerson._id || r.target === editPerson._id)

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import { Transition } from '@headlessui/react'; import { Transition } from '@headlessui/react';
import { FaTimes } from 'react-icons/fa'; import { FaTimes } from 'react-icons/fa';
@ -274,7 +274,7 @@ export const NetworkStats: React.FC<NetworkStatsProps> = ({ people, relationship
people.length > 0 ? (relationships.length / people.length).toFixed(1) : '0.0'; people.length > 0 ? (relationships.length / people.length).toFixed(1) : '0.0';
const isolatedPeople = people.filter( const isolatedPeople = people.filter(
person => !relationships.some(r => r.source === person._id || r.target === person._id) person => !relationships.some(r => r.source === person._id || r.target === person._id),
).length; ).length;
// Find most connected person // Find most connected person
@ -286,7 +286,7 @@ export const NetworkStats: React.FC<NetworkStatsProps> = ({ people, relationship
const mostConnected = const mostConnected =
personConnectionCounts.length > 0 personConnectionCounts.length > 0
? personConnectionCounts.reduce((prev, current) => ? personConnectionCounts.reduce((prev, current) =>
prev.count > current.count ? prev : current prev.count > current.count ? prev : current,
) )
: null; : null;

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom'; import { Link, useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from '../../context/AuthContext'; import { useAuth } from '../../context/AuthContext';
import { FaUser, FaSignOutAlt, FaNetworkWired } from 'react-icons/fa'; import { FaNetworkWired, FaSignOutAlt, FaUser } from 'react-icons/fa';
const Header: React.FC = () => { const Header: React.FC = () => {
const { user, logout } = useAuth(); const { user, logout } = useAuth();
@ -63,7 +63,8 @@ const Header: React.FC = () => {
</div> </div>
</button> </button>
<div className="absolute right-0 mt-2 w-48 bg-slate-800 rounded-md shadow-lg py-1 z-10 border border-slate-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200"> <div
className="absolute right-0 mt-2 w-48 bg-slate-800 rounded-md shadow-lg py-1 z-10 border border-slate-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<button <button
onClick={handleLogout} onClick={handleLogout}
className="w-full text-left px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 flex items-center" className="w-full text-left px-4 py-2 text-sm text-slate-300 hover:bg-slate-700 flex items-center"

View File

@ -2,8 +2,8 @@ import React, { useState } from 'react';
import { useNetworks } from '../../context/NetworkContext'; import { useNetworks } from '../../context/NetworkContext';
import { useAuth } from '../../context/AuthContext'; import { useAuth } from '../../context/AuthContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { FaPlus, FaNetworkWired, FaTrash, FaEye, FaGlobe, FaLock, FaTimes } from 'react-icons/fa'; import { FaEye, FaGlobe, FaLock, FaNetworkWired, FaPlus, FaTimes, FaTrash } from 'react-icons/fa';
const NetworkList: React.FC = () => { const NetworkList: React.FC = () => {
const { networks, loading, error, createNetwork, deleteNetwork } = useNetworks(); const { networks, loading, error, createNetwork, deleteNetwork } = useNetworks();

View File

@ -1,12 +1,12 @@
import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react'; import React, { createContext, ReactNode, useContext, useEffect, useState } from 'react';
import { import {
User,
getCurrentUser, getCurrentUser,
login as apiLogin, login as apiLogin,
register as apiRegister,
logout as apiLogout,
LoginData, LoginData,
logout as apiLogout,
register as apiRegister,
RegisterData, RegisterData,
User,
} from '../api/auth'; } from '../api/auth';
interface AuthContextProps { interface AuthContextProps {

View File

@ -1,11 +1,11 @@
import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react'; import React, { createContext, ReactNode, useContext, useEffect, useState } from 'react';
import { import {
Network,
getUserNetworks,
createNetwork as apiCreateNetwork, createNetwork as apiCreateNetwork,
updateNetwork as apiUpdateNetwork,
deleteNetwork as apiDeleteNetwork,
CreateNetworkData, CreateNetworkData,
deleteNetwork as apiDeleteNetwork,
getUserNetworks,
Network,
updateNetwork as apiUpdateNetwork,
UpdateNetworkData, UpdateNetworkData,
} from '../api/network'; } from '../api/network';
import { useAuth } from './AuthContext'; import { useAuth } from './AuthContext';

View File

@ -1,11 +1,11 @@
import { useState, useEffect, useCallback, useRef } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { Person, getPeople, addPerson, updatePerson, removePerson } from '../api/people'; import { addPerson, getPeople, Person, removePerson, updatePerson } from '../api/people';
import { import {
Relationship,
getRelationships,
addRelationship, addRelationship,
updateRelationship, getRelationships,
Relationship,
removeRelationship, removeRelationship,
updateRelationship,
} from '../api/relationships'; } from '../api/relationships';
interface PersonNode extends Person { interface PersonNode extends Person {
@ -24,7 +24,7 @@ const DEFAULT_POLL_INTERVAL = 5000;
// Custom hook to manage friendship network data // Custom hook to manage friendship network data
export const useFriendshipNetwork = ( export const useFriendshipNetwork = (
networkId: string | null, networkId: string | null,
pollInterval = DEFAULT_POLL_INTERVAL pollInterval = DEFAULT_POLL_INTERVAL,
) => { ) => {
const [people, setPeople] = useState<PersonNode[]>([]); const [people, setPeople] = useState<PersonNode[]>([]);
const [relationships, setRelationships] = useState<RelationshipEdge[]>([]); const [relationships, setRelationships] = useState<RelationshipEdge[]>([]);
@ -70,7 +70,7 @@ export const useFriendshipNetwork = (
// Generate hashes to detect changes // Generate hashes to detect changes
const positionsHash = JSON.stringify(peopleNodes.map(p => ({ id: p.id, pos: p.position }))); const positionsHash = JSON.stringify(peopleNodes.map(p => ({ id: p.id, pos: p.position })));
const relationshipsHash = JSON.stringify( const relationshipsHash = JSON.stringify(
relationshipEdges.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })) relationshipEdges.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })),
); );
// Handle people updates // Handle people updates
@ -187,7 +187,7 @@ export const useFriendshipNetwork = (
} }
} }
}, },
[networkId] [networkId],
); );
// Set up polling for network data // Set up polling for network data
@ -234,7 +234,7 @@ export const useFriendshipNetwork = (
// Update the reference hash to avoid unnecessary state updates on next poll // Update the reference hash to avoid unnecessary state updates on next poll
lastPeopleUpdateRef.current = JSON.stringify( lastPeopleUpdateRef.current = JSON.stringify(
updatedPeople.map(p => ({ id: p.id, pos: p.position })) updatedPeople.map(p => ({ id: p.id, pos: p.position })),
); );
return newPersonNode; return newPersonNode;
@ -252,7 +252,7 @@ export const useFriendshipNetwork = (
lastName?: string; lastName?: string;
birthday?: string | null; birthday?: string | null;
position?: { x: number; y: number }; position?: { x: number; y: number };
} },
): Promise<PersonNode> => { ): Promise<PersonNode> => {
if (!networkId) throw new Error('No network selected'); if (!networkId) throw new Error('No network selected');
@ -262,14 +262,14 @@ export const useFriendshipNetwork = (
// Update the local state // Update the local state
const updatedPeople = people.map(person => const updatedPeople = people.map(person =>
person._id === personId ? updatedPersonNode : person person._id === personId ? updatedPersonNode : person,
); );
setPeople(updatedPeople); setPeople(updatedPeople);
// Update the reference hash if position changed to avoid unnecessary state updates on next poll // Update the reference hash if position changed to avoid unnecessary state updates on next poll
if (personData.position) { if (personData.position) {
lastPeopleUpdateRef.current = JSON.stringify( lastPeopleUpdateRef.current = JSON.stringify(
updatedPeople.map(p => ({ id: p.id, pos: p.position })) updatedPeople.map(p => ({ id: p.id, pos: p.position })),
); );
} }
@ -293,16 +293,16 @@ export const useFriendshipNetwork = (
// Remove all relationships involving this person // Remove all relationships involving this person
const updatedRelationships = relationships.filter( const updatedRelationships = relationships.filter(
rel => rel.source !== personId && rel.target !== personId rel => rel.source !== personId && rel.target !== personId,
); );
setRelationships(updatedRelationships); setRelationships(updatedRelationships);
// Update both reference hashes to avoid unnecessary state updates on next poll // Update both reference hashes to avoid unnecessary state updates on next poll
lastPeopleUpdateRef.current = JSON.stringify( lastPeopleUpdateRef.current = JSON.stringify(
updatedPeople.map(p => ({ id: p.id, pos: p.position })) updatedPeople.map(p => ({ id: p.id, pos: p.position })),
); );
lastRelationshipsUpdateRef.current = JSON.stringify( lastRelationshipsUpdateRef.current = JSON.stringify(
updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })) updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })),
); );
} catch (err: any) { } catch (err: any) {
setError(err.message || 'Failed to delete person'); setError(err.message || 'Failed to delete person');
@ -328,7 +328,7 @@ export const useFriendshipNetwork = (
// Update the relationship hash to avoid unnecessary state updates on next poll // Update the relationship hash to avoid unnecessary state updates on next poll
lastRelationshipsUpdateRef.current = JSON.stringify( lastRelationshipsUpdateRef.current = JSON.stringify(
updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })) updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })),
); );
return newRelationshipEdge; return newRelationshipEdge;
@ -344,7 +344,7 @@ export const useFriendshipNetwork = (
relationshipData: { relationshipData: {
type?: 'freund' | 'partner' | 'familie' | 'arbeitskolleg' | 'custom'; type?: 'freund' | 'partner' | 'familie' | 'arbeitskolleg' | 'custom';
customType?: string; customType?: string;
} },
): Promise<RelationshipEdge> => { ): Promise<RelationshipEdge> => {
if (!networkId) throw new Error('No network selected'); if (!networkId) throw new Error('No network selected');
@ -352,7 +352,7 @@ export const useFriendshipNetwork = (
const updatedRelationship = await updateRelationship( const updatedRelationship = await updateRelationship(
networkId, networkId,
relationshipId, relationshipId,
relationshipData relationshipData,
); );
const updatedRelationshipEdge: RelationshipEdge = { const updatedRelationshipEdge: RelationshipEdge = {
...updatedRelationship, ...updatedRelationship,
@ -360,13 +360,13 @@ export const useFriendshipNetwork = (
}; };
const updatedRelationships = relationships.map(rel => const updatedRelationships = relationships.map(rel =>
rel._id === relationshipId ? updatedRelationshipEdge : rel rel._id === relationshipId ? updatedRelationshipEdge : rel,
); );
setRelationships(updatedRelationships); setRelationships(updatedRelationships);
// Update the relationship hash to avoid unnecessary state updates on next poll // Update the relationship hash to avoid unnecessary state updates on next poll
lastRelationshipsUpdateRef.current = JSON.stringify( lastRelationshipsUpdateRef.current = JSON.stringify(
updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })) updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })),
); );
return updatedRelationshipEdge; return updatedRelationshipEdge;
@ -387,7 +387,7 @@ export const useFriendshipNetwork = (
// Update the relationship hash to avoid unnecessary state updates on next poll // Update the relationship hash to avoid unnecessary state updates on next poll
lastRelationshipsUpdateRef.current = JSON.stringify( lastRelationshipsUpdateRef.current = JSON.stringify(
updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })) updatedRelationships.map(r => ({ id: r.id, src: r.source, tgt: r.target, type: r.type })),
); );
} catch (err: any) { } catch (err: any) {
setError(err.message || 'Failed to delete relationship'); setError(err.message || 'Failed to delete relationship');

View File

@ -11,7 +11,7 @@ if (rootElement) {
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode> </React.StrictMode>,
); );
} else { } else {
console.error('Root element not found'); console.error('Root element not found');