Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
•
Apple iOS & macOS13. Oktober nur der Anfang: Apples Hardware-Pläne bis 2029(01.10.2026 um 07:13 Uhr)
••
Android Tipps & SecurityWer ein Samsung-Handy hat, muss diese Internet-Einstellungen anpassen(01.10.2026 um 07:01 Uhr)
••
AI & KI NachrichtenThis Is Something Trump Can’t Break(01.10.2026 um 07:00 Uhr)
•
Sichere ProgrammierungThis Week In Rust: This Week in Rust 671(30.09.2026 um 06:00 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in ty (Fedora)(01.10.2026 um 07:54 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in rust-libcst (Fedora)(01.10.2026 um 07:54 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in rust-salsa-macro-rules (Fedora)(01.10.2026 um 07:54 Uhr)
••
Apple iOS & macOS13. Oktober nur der Anfang: Apples Hardware-Pläne bis 2029(01.10.2026 um 07:13 Uhr)
••
Android Tipps & SecurityWer ein Samsung-Handy hat, muss diese Internet-Einstellungen anpassen(01.10.2026 um 07:01 Uhr)
••
AI & KI NachrichtenThis Is Something Trump Can’t Break(01.10.2026 um 07:00 Uhr)
•
Sichere ProgrammierungThis Week In Rust: This Week in Rust 671(30.09.2026 um 06:00 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in ty (Fedora)(01.10.2026 um 07:54 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in rust-libcst (Fedora)(01.10.2026 um 07:54 Uhr)
•
Linux Tipps & HardeningSecurity: Zwei Probleme in rust-salsa-macro-rules (Fedora)(01.10.2026 um 07:54 Uhr)
•
Intelligence View
⚡ tsecurity.de Intelligence

Dart Object Oriented For Beginner : Expense Manager Case Study Part 5

Lesson 5: Adding Useful Features (Methods) Duration: 30 minutes App Feature: ✨ Making Expenses Smarter What You'll Build: Add helpful methods to analyze e…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!




Lesson 5: Adding Useful Features (Methods)



Duration: 30 minutes


App Feature: ✨ Making Expenses Smarter


What You'll Build: Add helpful methods to analyze expenses


Prerequisites: Complete Lessons 1-4







What We'll Learn Today



By the end of this lesson, you'll be able to:




  • ✅ Add methods that perform calculations

  • ✅ Create methods that return different types

  • ✅ Use optional and named parameters in methods

  • ✅ Build methods that check conditions

  • ✅ Format data for display

  • ✅ Make your Expense class more powerful







Part 1: Methods That Return Boolean Values



Let's add methods to check various conditions about an expense:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;

Expense(this._description, this._amount, this._category, this._date);

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;

// Boolean methods - return true or false
bool isMajorExpense() {
return _amount > 100;
}

bool isThisMonth() {
DateTime now = DateTime.now();
return _date.year == now.year && _date.month == now.month;
}

bool isThisWeek() {
DateTime now = DateTime.now();
DateTime startOfWeek = now.subtract(Duration(days: now.weekday - 1));
DateTime endOfWeek = startOfWeek.add(Duration(days: 6));
return _date.isAfter(startOfWeek) && _date.isBefore(endOfWeek);
}

bool isToday() {
DateTime now = DateTime.now();
return _date.year == now.year &&
_date.month == now.month &&
_date.day == now.day;
}

bool isCategory(String category) {
return _category == category;
}

bool isOlderThan(int days) {
DateTime now = DateTime.now();
int difference = now.difference(_date).inDays;
return difference > days;
}
}

void main() {
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

print('Coffee is major expense? ${coffee.isMajorExpense()}');
print('Coffee is this month? ${coffee.isThisMonth()}');
print('Coffee is today? ${coffee.isToday()}');
print('Coffee is Food? ${coffee.isCategory("Food")}');

print('\nLaptop is major expense? ${laptop.isMajorExpense()}');
print('Laptop is older than 3 days? ${laptop.isOlderThan(3)}');
}






Output:




Coffee is major expense? false
Coffee is this month? true
Coffee is today? true
Coffee is Food? true

Laptop is major expense? true
Laptop is older than 3 days? true












Part 2: Methods That Return Formatted Strings



Add methods that return nicely formatted data:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;

Expense(this._description, this._amount, this._category, this._date);

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;

// Formatting methods
String getFormattedAmount() {
return '\$${_amount.toStringAsFixed(2)}';
}

String getFormattedDate() {
List<String> months = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
];
return '${months[_date.month - 1]} ${_date.day}, ${_date.year}';
}

String getShortDate() {
return '${_date.month}/${_date.day}/${_date.year}';
}

String getSummary() {
String emoji = _amount > 100 ? '🔴' : '🟢';
return '$emoji $_description: ${getFormattedAmount()} [$_category]';
}

String getDetailedSummary() {
return '''
$_description
Amount:
${getFormattedAmount()}
Category:
$_category
Date:
${getFormattedDate()}
'''
;
}

String getCategoryEmoji() {
switch (_category) {
case 'Food': return '🍔';
case 'Transport': return '🚗';
case 'Bills': return '💡';
case 'Entertainment': return '🎬';
case 'Health': return '💊';
case 'Shopping': return '🛍️';
default: return '📝';
}
}

String getFullDisplay() {
return '${getCategoryEmoji()} $_description - ${getFormattedAmount()}';
}
}

void main() {
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

print(coffee.getSummary());
print(coffee.getFormattedDate());
print(coffee.getFullDisplay());

print('\n${laptop.getDetailedSummary()}');
}












Part 3: Methods with Calculations



Add methods that perform calculations:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;

Expense(this._description, this._amount, this._category, this._date);

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;

// Calculation methods
int getDaysAgo() {
DateTime now = DateTime.now();
return now.difference(_date).inDays;
}

double getTax({double taxRate = 0.10}) {
return _amount * taxRate;
}

double getTotalWithTax({double taxRate = 0.10}) {
return _amount + getTax(taxRate: taxRate);
}

double getPercentageOf(double total) {
if (total == 0) return 0;
return (_amount / total) * 100;
}

double getMonthlyAverage() {
// Assumes this is an annual expense
return _amount / 12;
}

// Split expense among people
double splitAmount(int numberOfPeople) {
if (numberOfPeople <= 0) return _amount;
return _amount / numberOfPeople;
}

// Calculate what this expense would be with a discount
double applyDiscount(double discountPercent) {
if (discountPercent < 0 || discountPercent > 100) {
return _amount;
}
return _amount * (1 - discountPercent / 100);
}
}

void main() {
var laptop = Expense('Laptop', 1000.0, 'Electronics', DateTime(2025, 10, 5));

print('Amount: \$${laptop.amount}');
print('Days ago: ${laptop.getDaysAgo()}');
print('Tax (10%): \$${laptop.getTax().toStringAsFixed(2)}');
print('Total with tax: \$${laptop.getTotalWithTax().toStringAsFixed(2)}');
print('Split 4 ways: \$${laptop.splitAmount(4).toStringAsFixed(2)}');
print('With 20% discount: \$${laptop.applyDiscount(20).toStringAsFixed(2)}');

double totalSpending = 5000.0;
print('Percentage of total: ${laptop.getPercentageOf(totalSpending).toStringAsFixed(1)}%');
}






Output:




Amount: $1000.0
Days ago: 4
Tax (10%): $100.00
Total with tax: $1100.00
Split 4 ways: $250.00
With 20% discount: $800.00
Percentage of total: 20.0%












Part 4: Methods with Optional Parameters



Create flexible methods using optional parameters:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;

Expense(this._description, this._amount, this._category, this._date);

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;

// Method with optional positional parameter
void printDetails([bool showEmoji = false]) {
String emoji = showEmoji ? getCategoryEmoji() : '';
print('$emoji $_description: \$${_amount.toStringAsFixed(2)} [$_category]');
}

// Method with multiple optional parameters
String format({
bool showDate = false,
bool showCategory = true,
bool showEmoji = false,
String currency = '\$',
}) {
String result = _description;

if (showEmoji) {
result = '${getCategoryEmoji()} $result';
}

result += ': $currency${_amount.toStringAsFixed(2)}';

if (showCategory) {
result += ' [$_category]';
}

if (showDate) {
result += ' (${_date.toString().split(' ')[0]})';
}

return result;
}

String getCategoryEmoji() {
switch (_category) {
case 'Food': return '🍔';
case 'Transport': return '🚗';
case 'Bills': return '💡';
default: return '📝';
}
}

// Method with optional callback
void process({void Function(String)? onComplete}) {
// Do some processing
print('Processing expense: $_description');

// Call callback if provided
if (onComplete != null) {
onComplete('✅ Expense processed successfully');
}
}
}

void main() {
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

// Different ways to call printDetails
coffee.printDetails();
coffee.printDetails(true);

// Different ways to format
print('\n${coffee.format()}');
print(coffee.format(showEmoji: true));
print(coffee.format(showDate: true, showEmoji: true));
print(coffee.format(currency: '€', showCategory: false));

// Using callback
print('');
coffee.process(onComplete: (message) {
print(message);
});
}












Part 5: Comparison Methods



Add methods to compare expenses:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;

Expense(this._description, this._amount, this._category, this._date);

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;

// Comparison methods
bool isMoreExpensiveThan(Expense other) {
return _amount > other._amount;
}

bool isSameCategory(Expense other) {
return _category == other._category;
}

bool isSameDay(Expense other) {
return _date.year == other._date.year &&
_date.month == other._date.month &&
_date.day == other._date.day;
}

bool isNewerThan(Expense other) {
return _date.isAfter(other._date);
}

int compareByAmount(Expense other) {
if (_amount < other._amount) return -1;
if (_amount > other._amount) return 1;
return 0;
}

int compareByDate(Expense other) {
return _date.compareTo(other._date);
}

double getDifferenceFrom(Expense other) {
return (_amount - other._amount).abs();
}
}

void main() {
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
var lunch = Expense('Lunch', 12.75, 'Food', DateTime.now());
var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

print('Lunch is more expensive than coffee? ${lunch.isMoreExpensiveThan(coffee)}');
print('Lunch same category as coffee? ${lunch.isSameCategory(coffee)}');
print('Lunch same day as coffee? ${lunch.isSameDay(coffee)}');
print('Coffee newer than laptop? ${coffee.isNewerThan(laptop)}');
print('Difference between lunch and coffee: \$${lunch.getDifferenceFrom(coffee).toStringAsFixed(2)}');
}












Part 6: Complete Enhanced Expense Class



Here's a comprehensive Expense class with all useful methods:




class Expense {
String _description;
double _amount;
String _category;
DateTime _date;
String? _notes;
bool _isPaid;

static const List<String> validCategories = [
'Food', 'Transport', 'Bills', 'Entertainment', 'Health', 'Shopping', 'Other'
];

Expense({
required String description,
required double amount,
required String category,
DateTime? date,
String? notes,
bool isPaid = false,
}) : _description = description,
_amount = amount,
_category = category,
_date = date ?? DateTime.now(),
_notes = notes,
_isPaid = isPaid {
if (_amount < 0) throw Exception('Amount cannot be negative');
if (_description.trim().isEmpty) throw Exception('Description cannot be empty');
if (!validCategories.contains(_category)) {
_category = 'Other';
}
}

// Getters
String get description => _description;
double get amount => _amount;
String get category => _category;
DateTime get date => _date;
String? get notes => _notes;
bool get isPaid => _isPaid;

// Setters
set amount(double value) {
if (value < 0) throw Exception('Amount cannot be negative');
_amount = value;
}

set isPaid(bool value) => _isPaid = value;
set notes(String? value) => _notes = value;

// Boolean check methods
bool isMajorExpense() => _amount > 100;
bool isThisMonth() {
DateTime now = DateTime.now();
return _date.year == now.year && _date.month == now.month;
}
bool isToday() {
DateTime now = DateTime.now();
return _date.year == now.year && _date.month == now.month && _date.day == now.day;
}
bool isCategory(String cat) => _category == cat;
bool isOlderThan(int days) => DateTime.now().difference(_date).inDays > days;

// Formatting methods
String getFormattedAmount() => '\$${_amount.toStringAsFixed(2)}';

String getFormattedDate() {
List<String> months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return '${months[_date.month - 1]} ${_date.day}, ${_date.year}';
}

String getCategoryEmoji() {
switch (_category) {
case 'Food': return '🍔';
case 'Transport': return '🚗';
case 'Bills': return '💡';
case 'Entertainment': return '🎬';
case 'Health': return '💊';
case 'Shopping': return '🛍️';
default: return '📝';
}
}

String getSummary() {
String emoji = isMajorExpense() ? '🔴' : '🟢';
return '$emoji $_description: ${getFormattedAmount()} [$_category]';
}

String getFullDisplay() {
String paid = _isPaid ? '✅' : '❌';
String noteText = _notes != null ? ' - $_notes' : '';
return '$paid ${getCategoryEmoji()} $_description: ${getFormattedAmount()}$noteText';
}

// Calculation methods
int getDaysAgo() => DateTime.now().difference(_date).inDays;

double getTax({double taxRate = 0.10}) => _amount * taxRate;

double getTotalWithTax({double taxRate = 0.10}) => _amount + getTax(taxRate: taxRate);

double getPercentageOf(double total) {
if (total == 0) return 0;
return (_amount / total) * 100;
}

double splitAmount(int numberOfPeople) {
if (numberOfPeople <= 0) return _amount;
return _amount / numberOfPeople;
}

// Comparison methods
bool isMoreExpensiveThan(Expense other) => _amount > other._amount;
bool isSameCategory(Expense other) => _category == other._category;
bool isNewerThan(Expense other) => _date.isAfter(other._date);

int compareByAmount(Expense other) {
if (_amount < other._amount) return -1;
if (_amount > other._amount) return 1;
return 0;
}

// Action methods
void markAsPaid() {
_isPaid = true;
}

void markAsUnpaid() {
_isPaid = false;
}

void addNote(String note) {
if (_notes == null || _notes!.isEmpty) {
_notes = note;
} else {
_notes = '$_notes; $note';
}
}

void printDetails() {
print('─────────────────────────────');
print('${getCategoryEmoji()} $_description');
print('💰 ${getFormattedAmount()}');
print('📁 $_category');
print('📅 ${getFormattedDate()}');
print('${_isPaid ? "✅" : "❌"} ${_isPaid ? "Paid" : "Unpaid"}');
if (_notes != null && _notes!.isNotEmpty) {
print('📝 $_notes');
}
print('🕒 ${getDaysAgo()} days ago');
}
}

void main() {
print('🏦 ENHANCED EXPENSE CLASS DEMO\n');

var expenses = [
Expense(description: 'Morning coffee', amount: 4.50, category: 'Food'),
Expense(description: 'Uber to work', amount: 12.00, category: 'Transport'),
Expense(description: 'Laptop', amount: 899.99, category: 'Shopping', isPaid: true),
Expense(description: 'Groceries', amount: 127.50, category: 'Food', notes: 'Weekly shopping'),
];

// Print all summaries
print('SUMMARY:');
for (var expense in expenses) {
print(expense.getSummary());
}

// Calculate totals
double total = 0;
for (var expense in expenses) {
total += expense.amount;
}

print('\n─────────────────────────────');
print('Total: \$${total.toStringAsFixed(2)}');

// Show percentages
print('\nPERCENTAGES:');
for (var expense in expenses) {
print('${expense.description}: ${expense.getPercentageOf(total).toStringAsFixed(1)}%');
}

// Show this month's expenses
print('\nTHIS MONTH:');
for (var expense in expenses) {
if (expense.isThisMonth()) {
print(expense.getFullDisplay());
}
}

// Show major expenses
print('\nMAJOR EXPENSES (>\$100):');
for (var expense in expenses) {
if (expense.isMajorExpense()) {
expense.printDetails();
}
}
}












🎯 Practice Exercises






Exercise 1: Time-Based Methods (Easy)



Add these methods to the Expense class:





  1. getWeekNumber() - returns the week number of the year


  2. getQuarter() - returns which quarter (1-4) the expense is in


  3. isWeekend() - returns true if expense was on Saturday or Sunday



Solution:




int getWeekNumber() {
int dayOfYear = int.parse(DateFormat("D").format(_date));
return ((dayOfYear - _date.weekday + 10) / 7).floor();
}

int getQuarter() {
return ((_date.month - 1) / 3).floor() + 1;
}

bool isWeekend() {
return _date.weekday == DateTime.saturday || _date.weekday == DateTime.sunday;
}

void main() {
var expense = Expense(
description: 'Weekend brunch',
amount: 45.00,
category: 'Food',
date: DateTime(2025, 10, 11), // Saturday
);

print('Quarter: ${expense.getQuarter()}');
print('Is weekend? ${expense.isWeekend()}');
}









Exercise 2: Statistical Methods (Medium)



Add these methods:





  1. getAmountRounded() - returns amount rounded to nearest dollar


  2. getDailyAverage(int days) - returns average per day over specified period


  3. projectedYearly() - if this was monthly, what would yearly total be?



Solution:




double getAmountRounded() {
return _amount.roundToDouble();
}

double getDailyAverage(int days) {
if (days <= 0) return 0;
return _amount / days;
}

double projectedYearly() {
return _amount * 12;
}

void main() {
var subscription = Expense(
description: 'Netflix',
amount: 15.99,
category: 'Entertainment',
);

print('Amount: ${subscription.getFormattedAmount()}');
print('Rounded: \$${subscription.getAmountRounded().toStringAsFixed(2)}');
print('Daily average (30 days): \$${subscription.getDailyAverage(30).toStringAsFixed(2)}');
print('Projected yearly: \$${subscription.projectedYearly().toStringAsFixed(2)}');
}









Exercise 3: Smart Analysis Methods (Hard)



Create these advanced methods:





  1. getRiskLevel() - returns 'Low', 'Medium', or 'High' based on amount


  2. getSavingSuggestion() - returns a tip for reducing this expense


  3. compareToAverage(double avgExpense) - returns how much above/below average



Solution:




String getRiskLevel() {
if (_amount < 50) return 'Low';
if (_amount < 200) return 'Medium';
return 'High';
}

String getSavingSuggestion() {
if (_category == 'Food' && _amount > 50) {
return 'Consider meal prepping to reduce food costs';
}
if (_category == 'Transport' && _amount > 100) {
return 'Look into public transportation or carpooling';
}
if (_category == 'Entertainment' && _amount > 50) {
return 'Try free entertainment options like parks or libraries';
}
if (_amount > 500) {
return 'Major purchase - ensure it aligns with your budget goals';
}
return 'Expense looks reasonable';
}

String compareToAverage(double avgExpense) {
double difference = _amount - avgExpense;
double percentDiff = (difference / avgExpense * 100).abs();

if (difference > 0) {
return '\$${difference.toStringAsFixed(2)} (${percentDiff.toStringAsFixed(1)}%) above average';
} else if (difference < 0) {
return '\$${difference.abs().toStringAsFixed(2)} (${percentDiff.toStringAsFixed(1)}%) below average';
} else {
return 'Exactly average';
}
}

void main() {
var lunch = Expense(description: 'Lunch', amount: 85.00, category: 'Food');

print('Risk level: ${lunch.getRiskLevel()}');
print('Suggestion: ${lunch.getSavingSuggestion()}');
print('vs Average: ${lunch.compareToAverage(50.0)}');
}












Common Mistakes & How to Fix Them






Mistake 1: Not Returning Values






// ❌ Wrong - method doesn't return anything
String getSummary() {
'$_description: \$${_amount}';
}

// ✅ Correct - use return
String getSummary() {
return '$_description: \$${_amount}';
}









Mistake 2: Forgetting to Handle Edge Cases






// ❌ Wrong - division by zero possible
double splitAmount(int numberOfPeople) {
return _amount / numberOfPeople;
}

// ✅ Correct - check for invalid input
double splitAmount(int numberOfPeople) {
if (numberOfPeople <= 0) return _amount;
return _amount / numberOfPeople;
}









Mistake 3: Not Using Named Parameters When Appropriate






// ❌ Wrong - hard to remember order
String format(bool showDate, bool showCategory, bool showEmoji) { ... }

// ✅ Correct - use named parameters
String format({bool showDate = false, bool showCategory = true, bool showEmoji = false}) { ... }









Mistake 4: Making Methods Too Complex






// ❌ Wrong - doing too much
String doEverything() {
// 100 lines of code doing multiple things
}

// ✅ Correct - separate concerns
String getSummary() { ... }
String getFormattedDate() { ... }
double calculateTotal() { ... }












Key Concepts Review



✅ Boolean methods return true/false for conditions


✅ Formatting methods return nicely formatted strings


✅ Calculation methods perform math and return results


✅ Optional parameters make methods flexible


✅ Comparison methods compare objects


✅ Action methods modify object state


✅ Keep methods focused - each does one thing well







Self-Check Questions





1. When should you use a method vs a computed getter?



Answer:





  • Method: When there are parameters, complex logic, or side effects


  • Getter: For simple property access or calculations without parameters

  • Example: getTax(taxRate: 0.15) is a method, isMajorExpense is a getter





2. What's the benefit of optional parameters?



Answer:

Optional parameters make methods flexible - users can provide values when needed but use defaults otherwise. This reduces the need for multiple method versions.





3. Why should methods be focused on one task?



Answer:




  • Easier to understand and test

  • More reusable in different contexts

  • Simpler to debug when issues arise

  • Follows "Single Responsibility Principle"







What's Next?



In Lesson 6: Managing Multiple Expenses, we'll learn:




  • Creating an ExpenseManager class

  • Working with lists of expenses

  • Filtering and sorting

  • Calculating totals across multiple expenses

  • Building reports



Example preview:




class ExpenseManager {
List<Expense> _expenses = [];

void addExpense(Expense expense) { ... }
double getTotalSpending() { ... }
List<Expense> getByCategory(String category) { ... }
List<Expense> getThisMonth() { ... }
Expense? getLargestExpense() { ... }
}






See you in Lesson 6! 🚀









Additional Resources




  • Try adding more methods to your Expense class

  • Think about what calculations would be useful for your app

  • Consider what formatting options users might want

  • Practice writing focused, single-purpose methods



Remember: Methods should make your objects useful and intelligent. Each method should do one thing well! 💪

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Dart Object Oriented For Beginner : Expense Manager Case Study Part 5

Thematisch verwandte Begriffe: Dart, Object, Oriented, Beginner · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag