diff --git a/backend/api/models.py b/backend/api/models.py
index a8b5559..9c8b5ac 100644
--- a/backend/api/models.py
+++ b/backend/api/models.py
@@ -128,6 +128,7 @@ class Notification(models.Model):
TYPE_CHOICES = [
('reply', 'Reply'),
('mention', 'Mention'),
+ ('follow', 'Follow'),
('ticket_new', 'New Ticket'),
('ticket_reply', 'Ticket Reply'),
('profile_comment', 'Profile Comment'),
diff --git a/backend/api/views.py b/backend/api/views.py
index 78e4af5..b3598e6 100644
--- a/backend/api/views.py
+++ b/backend/api/views.py
@@ -553,7 +553,16 @@ class UserViewSet(viewsets.ModelViewSet):
user_to_follow = self.get_object()
if user_to_follow == request.user:
return Response({'error': 'You cannot follow yourself'}, status=status.HTTP_400_BAD_REQUEST)
- request.user.following.add(user_to_follow)
+
+ if not request.user.following.filter(pk=user_to_follow.pk).exists():
+ request.user.following.add(user_to_follow)
+ # Notify the user being followed
+ Notification.objects.create(
+ recipient=user_to_follow,
+ actor=request.user,
+ notification_type='follow'
+ )
+
return Response({'status': 'followed'})
@action(detail=True, methods=['post'], permission_classes=[permissions.IsAuthenticated])
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 1f511a9..511c015 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -512,6 +512,9 @@ const App: React.FC = () => {
} else if (n.notification_type === 'profile_comment') {
handleNotificationClick(n);
navigate(`/profile/${user?.username}`);
+ } else if (n.notification_type === 'follow') {
+ handleNotificationClick(n);
+ navigate(`/profile/${n.actor_username}`);
} else {
handleNotificationClick(n);
}
@@ -541,6 +544,7 @@ const App: React.FC = () => {
{n.actor_username} {
n.notification_type === 'reply' ? `replied to your review on ${n.flavor_name}` :
n.notification_type === 'mention' ? `mentioned you on ${n.flavor_name}` :
+ n.notification_type === 'follow' ? t('community.notifFollow') :
n.notification_type === 'profile_comment' ? `left a message on your guestbook` :
n.notification_type === 'ticket_new' ? t('community.notifTicketNew') :
user?.is_superuser ? t('community.notifTicketReplyAdmin') : t('community.notifTicketReply')
diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts
index e98987e..3e9f089 100644
--- a/frontend/src/i18n.ts
+++ b/frontend/src/i18n.ts
@@ -141,6 +141,7 @@ const resources = {
"notifications": "Recent Notifications",
"notifReply": "replied",
"notifMention": "mentioned you",
+ "notifFollow": "started following you",
"notifTicketNew": "opened a new support ticket",
"notifTicketReply": "replied to your support ticket",
"notifTicketReplyAdmin": "replied to a support ticket",
@@ -381,6 +382,7 @@ const resources = {
"notifications": "Neueste Benachrichtigungen",
"notifReply": "hat geantwortet",
"notifMention": "hat dich erwähnt",
+ "notifFollow": "folgt dir jetzt",
"notifTicketNew": "hat ein neues Support-Ticket eröffnet",
"notifTicketReply": "hat auf dein Support-Ticket geantwortet",
"notifTicketReplyAdmin": "hat auf ein Support-Ticket geantwortet",
diff --git a/frontend/src/pages/CommunityFeed.tsx b/frontend/src/pages/CommunityFeed.tsx
index eeee4d1..a8baec1 100644
--- a/frontend/src/pages/CommunityFeed.tsx
+++ b/frontend/src/pages/CommunityFeed.tsx
@@ -385,22 +385,37 @@ const CommunityFeed: React.FC = ({ adminMode }) => {
{notifications.length === 0 ? (
{t('community.noNotifications')}
) : (
- notifications.map(n => (
- n.flavor_id && navigate(`/flavor/${n.flavor_id}`)} sx={{ py: 1.5 }}>
-
- {n.actor_username.charAt(0)}
-
-
- {n.actor_username} {n.notification_type === 'reply' ? t('community.notifReply') : t('community.notifMention')}
-
- }
- secondary={formatTimestamp(n.created_at)}
- secondaryTypographyProps={{ sx: { fontSize: '0.7rem' } }}
- />
-
- ))
+ notifications.map(n => {
+ const handleClick = () => {
+ if (n.notification_type === 'follow') {
+ navigate(`/profile/${n.actor_username}`);
+ } else if (n.flavor_id) {
+ navigate(`/flavor/${n.flavor_id}`);
+ }
+ };
+
+ return (
+
+
+ {n.actor_username.charAt(0)}
+
+
+ {n.actor_username} {
+ n.notification_type === 'reply' ? t('community.notifReply') :
+ n.notification_type === 'mention' ? t('community.notifMention') :
+ n.notification_type === 'follow' ? t('community.notifFollow') :
+ n.notification_type
+ }
+
+ }
+ secondary={formatTimestamp(n.created_at)}
+ secondaryTypographyProps={{ sx: { fontSize: '0.7rem' } }}
+ />
+
+ );
+ })
)}