✨ feat: Implementierung von Benachrichtigungen und sozialen Funktionen; Hinzufügen von API-Endpunkten für Benachrichtigungen, Benutzer-Follows und soziale Interaktionen; Verbesserung des Logging-Systems zur besseren Nachverfolgbarkeit von Systemereignissen.
This commit is contained in:
512
templates/social/discover.html
Normal file
512
templates/social/discover.html
Normal file
@@ -0,0 +1,512 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Entdecken{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="min-h-screen"
|
||||
x-data="{
|
||||
activeTab: 'users',
|
||||
users: [],
|
||||
posts: [],
|
||||
trending: [],
|
||||
loading: false,
|
||||
searchQuery: '',
|
||||
searchResults: [],
|
||||
searching: false,
|
||||
|
||||
async loadUsers() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch('/api/discover/users');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.users = data.users;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading users:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async loadPosts() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch('/api/discover/posts');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.posts = data.posts;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading posts:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async loadTrending() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await fetch('/api/discover/trending');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
this.trending = data.trending;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading trending:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async follow(userId, index) {
|
||||
try {
|
||||
const response = await fetch(`/api/users/${userId}/follow`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.users[index].is_following = data.is_following;
|
||||
this.users[index].follower_count = data.follower_count;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error following user:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async searchUsers() {
|
||||
if (!this.searchQuery.trim()) {
|
||||
this.searchResults = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.searching = true;
|
||||
try {
|
||||
const response = await fetch(`/api/search/users?q=${encodeURIComponent(this.searchQuery)}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.searchResults = data.users;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error searching users:', error);
|
||||
} finally {
|
||||
this.searching = false;
|
||||
}
|
||||
},
|
||||
|
||||
formatNumber(num) {
|
||||
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
|
||||
if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
|
||||
return num.toString();
|
||||
},
|
||||
|
||||
init() {
|
||||
this.loadUsers();
|
||||
}
|
||||
}"
|
||||
x-init="init()">
|
||||
|
||||
<!-- Header Section -->
|
||||
<div class="border-b"
|
||||
:class="darkMode ? 'border-gray-700 bg-gray-900/50' : 'border-gray-200 bg-white/50'">
|
||||
<div class="max-w-6xl mx-auto px-4 py-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'">
|
||||
Entdecken
|
||||
</h1>
|
||||
<p class="text-lg mt-1"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-600'">
|
||||
Finde neue Leute und interessante Inhalte
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Search Bar -->
|
||||
<div class="flex-1 max-w-md ml-8">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<i class="fas fa-search"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'></i>
|
||||
</div>
|
||||
<input
|
||||
x-model="searchQuery"
|
||||
@input.debounce.300ms="searchUsers()"
|
||||
type="text"
|
||||
class="block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-xl leading-5 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500/50 focus:border-purple-500"
|
||||
:class="darkMode
|
||||
? 'bg-gray-800 border-gray-600 text-white placeholder-gray-400'
|
||||
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'"
|
||||
placeholder="Nutzer suchen...">
|
||||
</div>
|
||||
|
||||
<!-- Search Results Dropdown -->
|
||||
<div x-show="searchQuery && searchResults.length > 0"
|
||||
x-transition
|
||||
class="absolute z-50 mt-2 w-full rounded-xl shadow-lg border"
|
||||
:class="darkMode
|
||||
? 'bg-gray-800 border-gray-600'
|
||||
: 'bg-white border-gray-200'">
|
||||
<template x-for="user in searchResults.slice(0, 5)">
|
||||
<div class="p-3 hover:bg-gray-50 transition-colors duration-150 cursor-pointer"
|
||||
:class="darkMode ? 'hover:bg-gray-700' : 'hover:bg-gray-50'"
|
||||
@click="window.location.href = `/profile/${user.username}`">
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center text-white font-semibold">
|
||||
<span x-text="user.username.charAt(0).toUpperCase()"></span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-medium"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="user.display_name || user.username"></p>
|
||||
<p class="text-sm"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'"
|
||||
x-text="`@${user.username}`"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab Navigation -->
|
||||
<div class="flex space-x-1 bg-gray-100 rounded-xl p-1"
|
||||
:class="darkMode ? 'bg-gray-800' : 'bg-gray-100'">
|
||||
<button @click="activeTab = 'users'; loadUsers()"
|
||||
class="flex-1 px-4 py-2 rounded-lg font-medium transition-all duration-200"
|
||||
:class="activeTab === 'users'
|
||||
? (darkMode ? 'bg-purple-600 text-white shadow-lg' : 'bg-white text-purple-600 shadow-md')
|
||||
: (darkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900')">
|
||||
<i class="fas fa-users mr-2"></i>
|
||||
Nutzer
|
||||
</button>
|
||||
|
||||
<button @click="activeTab = 'posts'; loadPosts()"
|
||||
class="flex-1 px-4 py-2 rounded-lg font-medium transition-all duration-200"
|
||||
:class="activeTab === 'posts'
|
||||
? (darkMode ? 'bg-purple-600 text-white shadow-lg' : 'bg-white text-purple-600 shadow-md')
|
||||
: (darkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900')">
|
||||
<i class="fas fa-fire mr-2"></i>
|
||||
Beliebte Posts
|
||||
</button>
|
||||
|
||||
<button @click="activeTab = 'trending'; loadTrending()"
|
||||
class="flex-1 px-4 py-2 rounded-lg font-medium transition-all duration-200"
|
||||
:class="activeTab === 'trending'
|
||||
? (darkMode ? 'bg-purple-600 text-white shadow-lg' : 'bg-white text-purple-600 shadow-md')
|
||||
: (darkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900')">
|
||||
<i class="fas fa-trending-up mr-2"></i>
|
||||
Im Trend
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Section -->
|
||||
<div class="max-w-6xl mx-auto px-4 py-8">
|
||||
|
||||
<!-- Loading State -->
|
||||
<div x-show="loading" class="text-center py-16">
|
||||
<div class="inline-flex items-center space-x-3"
|
||||
:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
|
||||
<svg class="animate-spin h-8 w-8" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="m4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<span class="text-lg">Lädt...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Users Tab -->
|
||||
<div x-show="activeTab === 'users' && !loading">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<template x-for="(user, index) in users" :key="user.id">
|
||||
<div class="rounded-2xl p-6 shadow-lg border transition-all duration-300 hover:shadow-xl transform hover:scale-105"
|
||||
:class="darkMode
|
||||
? 'bg-gray-800/90 border-gray-700/50 backdrop-blur-xl'
|
||||
: 'bg-white/80 border-gray-200/50 backdrop-blur-xl'">
|
||||
|
||||
<!-- User Avatar -->
|
||||
<div class="text-center mb-4">
|
||||
<div class="w-20 h-20 rounded-full bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center text-white font-bold text-2xl mx-auto shadow-lg">
|
||||
<span x-text="user.username.charAt(0).toUpperCase()"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Info -->
|
||||
<div class="text-center mb-4">
|
||||
<h3 class="text-xl font-bold mb-1"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="user.display_name || user.username"></h3>
|
||||
<p class="text-sm mb-2"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'"
|
||||
x-text="`@${user.username}`"></p>
|
||||
|
||||
<div x-show="user.bio" class="mb-3">
|
||||
<p class="text-sm"
|
||||
:class="darkMode ? 'text-gray-300' : 'text-gray-700'"
|
||||
x-text="user.bio"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Stats -->
|
||||
<div class="flex justify-center space-x-6 mb-4">
|
||||
<div class="text-center">
|
||||
<div class="text-lg font-bold"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="formatNumber(user.follower_count || 0)"></div>
|
||||
<div class="text-xs"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'">
|
||||
Follower
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-lg font-bold"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="formatNumber(user.following_count || 0)"></div>
|
||||
<div class="text-xs"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'">
|
||||
Folge ich
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-lg font-bold"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="formatNumber(user.post_count || 0)"></div>
|
||||
<div class="text-xs"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'">
|
||||
Posts
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex space-x-2">
|
||||
<button @click="follow(user.id, index)"
|
||||
class="flex-1 py-2 px-4 rounded-xl font-semibold transition-all duration-300 transform hover:scale-105"
|
||||
:class="user.is_following
|
||||
? (darkMode ? 'bg-gray-700 text-white border border-gray-600 hover:bg-gray-600' : 'bg-gray-100 text-gray-700 border border-gray-300 hover:bg-gray-200')
|
||||
: 'bg-gradient-to-r from-purple-500 to-indigo-500 text-white shadow-md hover:shadow-lg'">
|
||||
<span x-text="user.is_following ? 'Entfolgen' : 'Folgen'"></span>
|
||||
</button>
|
||||
|
||||
<button @click="window.location.href = `/profile/${user.username}`"
|
||||
class="px-4 py-2 rounded-xl transition-all duration-300 transform hover:scale-105"
|
||||
:class="darkMode
|
||||
? 'bg-gray-700 text-white border border-gray-600 hover:bg-gray-600'
|
||||
: 'bg-gray-100 text-gray-700 border border-gray-300 hover:bg-gray-200'">
|
||||
<i class="fas fa-user"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Empty State for Users -->
|
||||
<div x-show="!loading && users.length === 0" class="text-center py-16">
|
||||
<div class="mb-6">
|
||||
<i class="fas fa-users text-6xl mb-4"
|
||||
:class="darkMode ? 'text-gray-600' : 'text-gray-300'"></i>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold mb-2"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'">
|
||||
Keine Nutzer gefunden
|
||||
</h3>
|
||||
<p class="text-lg"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-600'">
|
||||
Versuche es später noch einmal oder ändere deine Suchkriterien.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Popular Posts Tab -->
|
||||
<div x-show="activeTab === 'posts' && !loading">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<template x-for="post in posts" :key="post.id">
|
||||
<article class="rounded-2xl p-6 shadow-lg border transition-all duration-300 hover:shadow-xl"
|
||||
:class="darkMode
|
||||
? 'bg-gray-800/90 border-gray-700/50 backdrop-blur-xl'
|
||||
: 'bg-white/80 border-gray-200/50 backdrop-blur-xl'">
|
||||
|
||||
<!-- Post Header -->
|
||||
<div class="flex items-center space-x-3 mb-4">
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center text-white font-semibold text-lg shadow-md">
|
||||
<span x-text="post.author.username.charAt(0).toUpperCase()"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center space-x-2">
|
||||
<h4 class="font-semibold truncate"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="post.author.display_name || post.author.username"></h4>
|
||||
<span x-show="post.author.is_verified"
|
||||
class="text-blue-500">
|
||||
<i class="fas fa-check-circle text-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'"
|
||||
x-text="formatTimeAgo(post.created_at)"></p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-1 text-sm px-2 py-1 rounded-full"
|
||||
:class="darkMode ? 'bg-red-500/20 text-red-400' : 'bg-red-50 text-red-500'">
|
||||
<i class="fas fa-fire"></i>
|
||||
<span>Trending</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Post Content -->
|
||||
<div class="mb-4">
|
||||
<p class="text-lg leading-relaxed"
|
||||
:class="darkMode ? 'text-gray-100' : 'text-gray-800'"
|
||||
x-text="post.content"></p>
|
||||
</div>
|
||||
|
||||
<!-- Post Stats -->
|
||||
<div class="flex items-center space-x-6 text-sm"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'">
|
||||
<div class="flex items-center space-x-1">
|
||||
<i class="fas fa-heart"></i>
|
||||
<span x-text="formatNumber(post.like_count || 0)"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-1">
|
||||
<i class="far fa-comment"></i>
|
||||
<span x-text="formatNumber(post.comment_count || 0)"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-1">
|
||||
<i class="fas fa-share"></i>
|
||||
<span x-text="formatNumber(post.share_count || 0)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Empty State for Posts -->
|
||||
<div x-show="!loading && posts.length === 0" class="text-center py-16">
|
||||
<div class="mb-6">
|
||||
<i class="fas fa-fire text-6xl mb-4"
|
||||
:class="darkMode ? 'text-gray-600' : 'text-gray-300'"></i>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold mb-2"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'">
|
||||
Keine beliebten Posts
|
||||
</h3>
|
||||
<p class="text-lg"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-600'">
|
||||
Noch keine Posts sind viral gegangen. Sei der Erste!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trending Tab -->
|
||||
<div x-show="activeTab === 'trending' && !loading">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<template x-for="item in trending" :key="item.id">
|
||||
<div class="rounded-2xl p-6 shadow-lg border transition-all duration-300 hover:shadow-xl transform hover:scale-105"
|
||||
:class="darkMode
|
||||
? 'bg-gray-800/90 border-gray-700/50 backdrop-blur-xl'
|
||||
: 'bg-white/80 border-gray-200/50 backdrop-blur-xl'">
|
||||
|
||||
<div class="flex items-center space-x-3 mb-4">
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-orange-500 to-red-500 flex items-center justify-center text-white shadow-md">
|
||||
<i class="fas fa-hashtag text-lg"></i>
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<h3 class="font-bold text-lg"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'"
|
||||
x-text="item.title"></h3>
|
||||
<p class="text-sm"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-500'"
|
||||
x-text="`${formatNumber(item.count)} Posts`"></p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-1 text-sm px-2 py-1 rounded-full"
|
||||
:class="darkMode ? 'bg-orange-500/20 text-orange-400' : 'bg-orange-50 text-orange-500'">
|
||||
<i class="fas fa-trending-up"></i>
|
||||
<span x-text="`+${item.growth}%`"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="item.description" class="mb-4">
|
||||
<p class="text-sm"
|
||||
:class="darkMode ? 'text-gray-300' : 'text-gray-700'"
|
||||
x-text="item.description"></p>
|
||||
</div>
|
||||
|
||||
<button class="w-full py-2 px-4 rounded-xl font-semibold transition-all duration-300 transform hover:scale-105"
|
||||
:class="darkMode
|
||||
? 'bg-gray-700 text-white border border-gray-600 hover:bg-gray-600'
|
||||
: 'bg-gray-100 text-gray-700 border border-gray-300 hover:bg-gray-200'">
|
||||
Erkunden
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Empty State for Trending -->
|
||||
<div x-show="!loading && trending.length === 0" class="text-center py-16">
|
||||
<div class="mb-6">
|
||||
<i class="fas fa-trending-up text-6xl mb-4"
|
||||
:class="darkMode ? 'text-gray-600' : 'text-gray-300'"></i>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold mb-2"
|
||||
:class="darkMode ? 'text-white' : 'text-gray-900'">
|
||||
Noch nichts im Trend
|
||||
</h3>
|
||||
<p class="text-lg"
|
||||
:class="darkMode ? 'text-gray-400' : 'text-gray-600'">
|
||||
Sei der Erste, der etwas Trending macht!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions Floating Button -->
|
||||
<div class="fixed bottom-6 right-6 z-40">
|
||||
<div class="relative group">
|
||||
<!-- Main FAB -->
|
||||
<button class="w-14 h-14 rounded-full bg-gradient-to-r from-purple-500 to-indigo-500 text-white shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-purple-500/50">
|
||||
<i class="fas fa-plus text-xl"></i>
|
||||
</button>
|
||||
|
||||
<!-- Action Menu -->
|
||||
<div class="absolute bottom-16 right-0 opacity-0 group-hover:opacity-100 transition-all duration-300 transform scale-95 group-hover:scale-100 space-y-2">
|
||||
<a href="{{ url_for('social_feed') }}"
|
||||
class="flex items-center justify-center w-12 h-12 rounded-full bg-blue-500 text-white shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-110"
|
||||
title="Zum Feed">
|
||||
<i class="fas fa-stream"></i>
|
||||
</a>
|
||||
|
||||
<button class="flex items-center justify-center w-12 h-12 rounded-full bg-green-500 text-white shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-110"
|
||||
title="Post erstellen">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Helper function for time formatting
|
||||
function formatTimeAgo(dateString) {
|
||||
const date = new Date(dateString);
|
||||
const now = new Date();
|
||||
const diffInSeconds = Math.floor((now - date) / 1000);
|
||||
|
||||
if (diffInSeconds < 60) return 'vor wenigen Sekunden';
|
||||
if (diffInSeconds < 3600) return `vor ${Math.floor(diffInSeconds / 60)} Min`;
|
||||
if (diffInSeconds < 86400) return `vor ${Math.floor(diffInSeconds / 3600)} Std`;
|
||||
return `vor ${Math.floor(diffInSeconds / 86400)} Tagen`;
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user