Skip to content

Commit 07f9424

Browse files
add avatars and icons
1 parent 6414548 commit 07f9424

File tree

12 files changed

+177
-344
lines changed

12 files changed

+177
-344
lines changed

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="" />
5+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>CTable</title>
88
</head>

frontend/public/favicon.svg

Lines changed: 16 additions & 0 deletions
Loading

frontend/src/components/domain/Postcard/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as ModalS from '../../common/Modal/styles';
1111
import { CreateComment, GetComments, DeleteComment } from '../../../API/Comment';
1212
import type { CommentProps } from '../../../API/Comment';
1313
import { useAuth } from '../../../API/AuthContext';
14+
import { getAvatarUrl } from '../../../utils/getAvatarurl';
1415

1516
const TrashIcon = () => (
1617
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
@@ -204,7 +205,13 @@ export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Proj
204205
)}
205206

206207
<S.PostHeader>
207-
<img src={(post as any).avatarUrl || 'url_placeholder_avatar.png'} alt={post.title} />
208+
<img // Tenta usar o username do autor como "semente".
209+
// Se não tiver, tenta o título do autor ou usa 'visitante' como fallback.
210+
src={getAvatarUrl(post.authorUsername || (post as any).author?.title || 'visitante')}
211+
alt="Avatar do autor"
212+
// Garante que fique redondinho igual ao perfil
213+
style={{ borderRadius: '50%', objectFit: 'cover', width: '40px', height: '40px' }}
214+
/>
208215
<span>{post.title}</span>
209216
<small>{(post as any).author?.title || 'Autor'}</small>
210217
</S.PostHeader>

frontend/src/components/layout/Header/Header.spec.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ interface StyleProps {
1010
to?: string;
1111
}
1212

13+
vi.mock('../../../API/AuthContext', () => ({
14+
useAuth: () => ({
15+
currentUser: { username: 'testuser' } // Simula um usuário logado para o Avatar aparecer
16+
})
17+
}));
18+
19+
1320
// Mock dos estilos
1421
vi.mock('./styles', () => ({
1522
HeaderContainer: ({ children }: StyleProps) => <header>{children}</header>,

frontend/src/components/layout/Header/index.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
import { FiPlus } from 'react-icons/fi';
22
import Searchbar from '../../domain/Searchbar';
33
import * as S from './styles';
4+
import { useAuth } from '../../../API/AuthContext';
5+
import { getAvatarUrl } from '../../../utils/getAvatarurl';
46

57

68
interface HeaderProps {
79
onCreateClick: () => void;
810
}
911

1012
export default function Header({ onCreateClick }: HeaderProps) {
13+
14+
const { currentUser } = useAuth();
15+
1116
return (
1217
<S.HeaderContainer>
1318
<S.SearchContainer>
@@ -21,6 +26,10 @@ export default function Header({ onCreateClick }: HeaderProps) {
2126
</S.CreateButton>
2227

2328
<S.ProfileIcon to={`/profile`}>
29+
<img
30+
src={getAvatarUrl(currentUser?.username || 'user')}
31+
alt="Meu Perfil"
32+
/>
2433
</S.ProfileIcon>
2534
</S.ActionsContainer>
2635
</S.HeaderContainer>

frontend/src/components/layout/Sidebar/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as S from './styles';
55
import type { CommunityProps } from '../../../API/Community';
66
import { useAuth } from '../../../API/AuthContext';
77
import { useEffect } from 'react';
8+
import { getAvatarUrl } from '../../../utils/getAvatarurl'
89

910
export default function Sidebar() {
1011
// Estado para controlar se a lista de comunidades está visível
@@ -56,6 +57,7 @@ export default function Sidebar() {
5657
key={community.communityID}
5758
>
5859
<S.CommunityIcon
60+
src={getAvatarUrl(community.name || 'comunidade', 'identicon')}
5961
alt={`${community.name} icon`}
6062
/>
6163
<span>{community.name}</span>

frontend/src/pages/CommunityPage/index.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import * as D from '../../components/common/Dropdown/styles';
1212
import Modal from '../../components/common/Modal';
1313
import * as ModalS from '../../components/common/Modal/styles';
1414
import { Loading } from '../../components/common/Loading'
15-
15+
import {getAvatarUrl} from '../../utils/getAvatarurl'
1616

1717
export default function CommunityPage() {
1818
const { communityID } = useParams<{ communityID: string }>();
@@ -67,11 +67,10 @@ export default function CommunityPage() {
6767
try {
6868
await JoinCommunity(community.communityID);
6969

70-
// Atualiza a interface após entrar na comunidade
7170
setCommunity((prev: CommunityProps | null) => prev ? ({
7271
...prev,
73-
isMember: true, // Esconde o botão
74-
memberCount: (prev.memberCount || 0) + 1 // Atualiza o contador visualmente
72+
isMember: true,
73+
memberCount: (prev.memberCount || 0) + 1
7574
}) : null);
7675

7776
setNotification({ message: 'Você entrou na comunidade!', type: 'success' });
@@ -94,7 +93,6 @@ export default function CommunityPage() {
9493
setNotification({ message: 'Comunidade excluída com sucesso.', type: 'success' });
9594
setIsDeleteModalOpen(false);
9695

97-
// Redireciona para home após excluir
9896
setTimeout(() => {
9997
navigate('/feed');
10098
}, 1500);
@@ -113,15 +111,14 @@ export default function CommunityPage() {
113111
try {
114112
await LeaveCommunity(community.communityID);
115113

116-
// Atualiza a interface
117114
setCommunity((prev: CommunityProps | null) => prev ? ({
118115
...prev,
119-
isMember: false, // O usuário não é mais membro
120-
memberCount: Math.max((prev.memberCount || 0) - 1, 0) // Decrementa contador
116+
isMember: false,
117+
memberCount: Math.max((prev.memberCount || 0) - 1, 0)
121118
}) : null);
122119

123120
setNotification({ message: 'Você saiu da comunidade.', type: 'success' });
124-
setIsLeaveModalOpen(false); // Fecha o modal
121+
setIsLeaveModalOpen(false);
125122

126123
} catch (error) {
127124
if (error instanceof Error) {
@@ -172,7 +169,10 @@ export default function CommunityPage() {
172169
<S.Banner />
173170

174171
<S.HeaderContainer>
175-
<S.Avatar />
172+
<S.Avatar
173+
src={getAvatarUrl(community.name || 'comunidade', 'identicon')}
174+
alt={`Avatar da comunidade ${community.name}`}
175+
/>
176176
<S.HeaderInfo>
177177
<h1>{community.name}</h1>
178178
<span>{community.memberCount} membros</span>

frontend/src/pages/CommunityPage/styles.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,28 +82,21 @@ export const HeaderContainer = styled.div`
8282
}
8383
`;
8484

85-
export const Avatar = styled.div`
85+
export const Avatar = styled.img`
8686
width: 130px;
8787
height: 130px;
88-
border-radius: 24px;
89-
background: linear-gradient(135deg, ${props => props.theme.sidebar} 0%, ${props => props.theme.button} 100%);
88+
border-radius: 24px; /* Identicons ficam ótimos quadrados com bordas arredondadas */
89+
90+
/* Garante que a imagem não distorça */
91+
object-fit: cover;
92+
93+
/* Cor de fundo enquanto carrega */
94+
background-color: ${props => props.theme.sidebar};
95+
9096
border: 5px solid ${props => props.theme.white};
9197
flex-shrink: 0;
9298
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2),
9399
0 4px 12px rgba(0, 0, 0, 0.15);
94-
position: relative;
95-
96-
/* Efeito de brilho */
97-
&::after {
98-
content: '';
99-
position: absolute;
100-
top: 15%;
101-
left: 15%;
102-
width: 35%;
103-
height: 35%;
104-
background: radial-gradient(circle, rgba(255, 255, 255, 0.4) 0%, transparent 70%);
105-
border-radius: 50%;
106-
}
107100
108101
transition: transform 0.3s ease, box-shadow 0.3s ease;
109102

frontend/src/pages/Profile/Profile.spec.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ describe('Página Profile', () => {
145145
fireEvent.click(confirmBtn);
146146

147147
await waitFor(() => {
148-
expect(screen.getByTestId('toast')).toHaveTextContent('Conta já encerrada');
148+
expect(logoutMock).toHaveBeenCalled();
149+
expect(navigateMock).toHaveBeenCalledWith('/login');
149150
});
150151
});
151152

0 commit comments

Comments
 (0)