Mobile fixes: - Add viewport meta tag (was missing, causing broken mobile rendering) - Make header nav controls visible on mobile (opacity-0 group-hover was invisible on touch) - Add touch swipe gestures for day navigation on mobile - Fix viewDays responsive override after profile load Bug fixes: - Fix goal save (WeeklyView used POST but route only had GET/PUT; fix to use PUT, add POST alias) - Fix body key mismatch (goal → text) in goal save request Auth & identity (Task 1): - Add accountNumber (auto-increment) to User model for stable identity - Fix OAuth flows: pass user CUID in state instead of email - Google/Outlook callbacks now look up users by ID, not email - Non-Gmail users can now connect Google Calendar/Tasks CalDAV performance (Task 5): - Embed CalDAV object URL in Apple event IDs (caldav::<url>::<uid> format) - Delete/update now use O(1) direct URL access instead of O(n) full calendar scan - Optimistic UI removal on delete (no blocking force-refresh) - Legacy fallback for old-format IDs during transition Apple Calendar data (Task 2): - Pass URL, location, recurringEventId, isRecurring through full pipeline - Add url, recurringEventId, isRecurring to CachedCalendarEvent schema - Calendar cache now reads/writes all new fields Projects (Task 6): - New Project model (name, icon, color, description, order) - CRUD API at /api/tasks/projects - Tasks now support optional projectId with cascading nullify Quotes (Task 4): - Curated local quote database (50 quotes, DE+EN) with tag filtering - Preset quote source APIs (ZenQuotes, Quotable, Forismatic, Type.fit) Fonts (Task 7): - FontPicker component with searchable dropdown and live preview - /api/fonts endpoint (Google Fonts API proxy with 24h cache, fallback to 40 popular fonts) Quick Settings (Task 8): - QuickSettingsSidebar component (font size, spacing, show completed, start day, show lines) - New user preferences: showCompletedTasks, showLines, startDayOffset, quoteSourceUrls v1.9.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
384 lines
11 KiB
TypeScript
384 lines
11 KiB
TypeScript
// quotes.ts - Curated quotes collection and utility functions
|
|
|
|
export interface LocalQuote {
|
|
text: string;
|
|
author: string;
|
|
language: "de" | "en";
|
|
tags: string[];
|
|
}
|
|
|
|
export const PRESET_QUOTE_SOURCES = [
|
|
{
|
|
name: "ZenQuotes",
|
|
url: "https://zenquotes.io/api/random",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom", "life"],
|
|
},
|
|
{
|
|
name: "Quotable",
|
|
url: "https://api.quotable.io/random",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom", "success", "life"],
|
|
},
|
|
{
|
|
name: "Forismatic",
|
|
url: "https://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=de",
|
|
language: "de",
|
|
tags: ["motivation", "wisdom", "life"],
|
|
},
|
|
{
|
|
name: "Type.fit",
|
|
url: "https://type.fit/api/quotes",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom"],
|
|
},
|
|
] as const;
|
|
|
|
export const LOCAL_QUOTES: LocalQuote[] = [
|
|
// --- German Quotes ---
|
|
{
|
|
text: "Es ist nicht genug zu wissen, man muss auch anwenden; es ist nicht genug zu wollen, man muss auch tun.",
|
|
author: "Johann Wolfgang von Goethe",
|
|
language: "de",
|
|
tags: ["motivation", "work", "perseverance"],
|
|
},
|
|
{
|
|
text: "Wer immer tut, was er schon kann, bleibt immer das, was er schon ist.",
|
|
author: "Henry Ford",
|
|
language: "de",
|
|
tags: ["motivation", "success", "perseverance"],
|
|
},
|
|
{
|
|
text: "Der Zweck des Lebens ist das Leben selbst.",
|
|
author: "Johann Wolfgang von Goethe",
|
|
language: "de",
|
|
tags: ["life", "wisdom"],
|
|
},
|
|
{
|
|
text: "Man muss das Unmogliche versuchen, um das Mogliche zu erreichen.",
|
|
author: "Hermann Hesse",
|
|
language: "de",
|
|
tags: ["motivation", "perseverance"],
|
|
},
|
|
{
|
|
text: "Wer nicht kann, was er will, muss wollen, was er kann.",
|
|
author: "Friedrich Schiller",
|
|
language: "de",
|
|
tags: ["wisdom", "perseverance", "life"],
|
|
},
|
|
{
|
|
text: "Es hort doch jeder nur, was er versteht.",
|
|
author: "Johann Wolfgang von Goethe",
|
|
language: "de",
|
|
tags: ["wisdom", "life"],
|
|
},
|
|
{
|
|
text: "Ohne Musik ware das Leben ein Irrtum.",
|
|
author: "Friedrich Nietzsche",
|
|
language: "de",
|
|
tags: ["life", "creativity"],
|
|
},
|
|
{
|
|
text: "Wege entstehen dadurch, dass man sie geht.",
|
|
author: "Franz Kafka",
|
|
language: "de",
|
|
tags: ["motivation", "perseverance", "life"],
|
|
},
|
|
{
|
|
text: "Der Mensch ist nichts anderes als wozu er sich macht.",
|
|
author: "Jean-Paul Sartre",
|
|
language: "de",
|
|
tags: ["wisdom", "life", "motivation"],
|
|
},
|
|
{
|
|
text: "Wer kampft, kann verlieren. Wer nicht kampft, hat schon verloren.",
|
|
author: "Bertolt Brecht",
|
|
language: "de",
|
|
tags: ["motivation", "perseverance", "success"],
|
|
},
|
|
{
|
|
text: "Die Grenzen meiner Sprache bedeuten die Grenzen meiner Welt.",
|
|
author: "Ludwig Wittgenstein",
|
|
language: "de",
|
|
tags: ["wisdom", "creativity"],
|
|
},
|
|
{
|
|
text: "Was mich nicht umbringt, macht mich starker.",
|
|
author: "Friedrich Nietzsche",
|
|
language: "de",
|
|
tags: ["perseverance", "motivation"],
|
|
},
|
|
{
|
|
text: "Phantasie ist wichtiger als Wissen, denn Wissen ist begrenzt.",
|
|
author: "Albert Einstein",
|
|
language: "de",
|
|
tags: ["creativity", "wisdom"],
|
|
},
|
|
{
|
|
text: "Nur wer sein Ziel kennt, findet den Weg.",
|
|
author: "Laozi",
|
|
language: "de",
|
|
tags: ["wisdom", "motivation", "success"],
|
|
},
|
|
{
|
|
text: "Die beste Zeit einen Baum zu pflanzen war vor zwanzig Jahren. Die zweitbeste Zeit ist jetzt.",
|
|
author: "Konfuzius",
|
|
language: "de",
|
|
tags: ["wisdom", "motivation", "work"],
|
|
},
|
|
{
|
|
text: "Auch aus Steinen, die einem in den Weg gelegt werden, kann man Schones bauen.",
|
|
author: "Johann Wolfgang von Goethe",
|
|
language: "de",
|
|
tags: ["perseverance", "creativity", "life"],
|
|
},
|
|
{
|
|
text: "Handle, ehe du gehandelt wirst.",
|
|
author: "Friedrich Schiller",
|
|
language: "de",
|
|
tags: ["motivation", "work"],
|
|
},
|
|
{
|
|
text: "Geduld ist das Vertrauen, dass alles kommt, wenn die Zeit reif ist.",
|
|
author: "Konfuzius",
|
|
language: "de",
|
|
tags: ["wisdom", "perseverance", "life"],
|
|
},
|
|
{
|
|
text: "Im Wesen der Musik liegt es, Freude zu machen.",
|
|
author: "Aristoteles",
|
|
language: "de",
|
|
tags: ["creativity", "life", "humor"],
|
|
},
|
|
{
|
|
text: "Lache nie uber die Dummheit der anderen. Sie ist deine Chance.",
|
|
author: "Winston Churchill",
|
|
language: "de",
|
|
tags: ["humor", "success", "wisdom"],
|
|
},
|
|
{
|
|
text: "Leben ist das, was passiert, wahrend du eifrig dabei bist, andere Plane zu machen.",
|
|
author: "John Lennon",
|
|
language: "de",
|
|
tags: ["life", "humor", "wisdom"],
|
|
},
|
|
{
|
|
text: "Der Langsamste, der sein Ziel nicht aus den Augen verliert, geht noch immer geschwinder als jener, der ohne Ziel umherirrt.",
|
|
author: "Gotthold Ephraim Lessing",
|
|
language: "de",
|
|
tags: ["perseverance", "motivation", "work"],
|
|
},
|
|
{
|
|
text: "Ein Tropfen Humor auf einen Zentner Verstand.",
|
|
author: "Friedrich Nietzsche",
|
|
language: "de",
|
|
tags: ["humor", "wisdom"],
|
|
},
|
|
// --- English Quotes ---
|
|
{
|
|
text: "The only way to do great work is to love what you do.",
|
|
author: "Steve Jobs",
|
|
language: "en",
|
|
tags: ["work", "motivation", "success"],
|
|
},
|
|
{
|
|
text: "Stay hungry, stay foolish.",
|
|
author: "Steve Jobs",
|
|
language: "en",
|
|
tags: ["motivation", "creativity"],
|
|
},
|
|
{
|
|
text: "Life is what happens when you are busy making other plans.",
|
|
author: "John Lennon",
|
|
language: "en",
|
|
tags: ["life", "wisdom"],
|
|
},
|
|
{
|
|
text: "In the middle of difficulty lies opportunity.",
|
|
author: "Albert Einstein",
|
|
language: "en",
|
|
tags: ["perseverance", "motivation", "success"],
|
|
},
|
|
{
|
|
text: "The unexamined life is not worth living.",
|
|
author: "Socrates",
|
|
language: "en",
|
|
tags: ["wisdom", "life"],
|
|
},
|
|
{
|
|
text: "Be yourself; everyone else is already taken.",
|
|
author: "Oscar Wilde",
|
|
language: "en",
|
|
tags: ["life", "wisdom", "humor"],
|
|
},
|
|
{
|
|
text: "To live is the rarest thing in the world. Most people exist, that is all.",
|
|
author: "Oscar Wilde",
|
|
language: "en",
|
|
tags: ["life", "wisdom"],
|
|
},
|
|
{
|
|
text: "The man who moves a mountain begins by carrying away small stones.",
|
|
author: "Konfuzius",
|
|
language: "en",
|
|
tags: ["perseverance", "motivation", "work"],
|
|
},
|
|
{
|
|
text: "It is not because things are difficult that we do not dare; it is because we do not dare that they are difficult.",
|
|
author: "Seneca",
|
|
language: "en",
|
|
tags: ["motivation", "perseverance", "wisdom"],
|
|
},
|
|
{
|
|
text: "The happiness of your life depends upon the quality of your thoughts.",
|
|
author: "Marcus Aurelius",
|
|
language: "en",
|
|
tags: ["wisdom", "life"],
|
|
},
|
|
{
|
|
text: "Waste no more time arguing about what a good man should be. Be one.",
|
|
author: "Marcus Aurelius",
|
|
language: "en",
|
|
tags: ["wisdom", "motivation", "work"],
|
|
},
|
|
{
|
|
text: "If you want to lift yourself up, lift up someone else.",
|
|
author: "Booker T. Washington",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom", "life"],
|
|
},
|
|
{
|
|
text: "Darkness cannot drive out darkness; only light can do that.",
|
|
author: "Martin Luther King Jr.",
|
|
language: "en",
|
|
tags: ["wisdom", "life", "motivation"],
|
|
},
|
|
{
|
|
text: "The time is always right to do what is right.",
|
|
author: "Martin Luther King Jr.",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom", "work"],
|
|
},
|
|
{
|
|
text: "There is no greater agony than bearing an untold story inside you.",
|
|
author: "Maya Angelou",
|
|
language: "en",
|
|
tags: ["creativity", "life"],
|
|
},
|
|
{
|
|
text: "We delight in the beauty of the butterfly, but rarely admit the changes it has gone through to achieve that beauty.",
|
|
author: "Maya Angelou",
|
|
language: "en",
|
|
tags: ["perseverance", "life", "wisdom"],
|
|
},
|
|
{
|
|
text: "The secret of getting ahead is getting started.",
|
|
author: "Mark Twain",
|
|
language: "en",
|
|
tags: ["motivation", "work", "success"],
|
|
},
|
|
{
|
|
text: "Whenever you find yourself on the side of the majority, it is time to pause and reflect.",
|
|
author: "Mark Twain",
|
|
language: "en",
|
|
tags: ["wisdom", "creativity"],
|
|
},
|
|
{
|
|
text: "Twenty years from now you will be more disappointed by the things you did not do than by the ones you did.",
|
|
author: "Mark Twain",
|
|
language: "en",
|
|
tags: ["motivation", "life", "perseverance"],
|
|
},
|
|
{
|
|
text: "It does not matter how slowly you go as long as you do not stop.",
|
|
author: "Konfuzius",
|
|
language: "en",
|
|
tags: ["perseverance", "motivation"],
|
|
},
|
|
{
|
|
text: "Success is not final, failure is not fatal: it is the courage to continue that counts.",
|
|
author: "Winston Churchill",
|
|
language: "en",
|
|
tags: ["perseverance", "success", "motivation"],
|
|
},
|
|
{
|
|
text: "The best time to plant a tree was 20 years ago. The second best time is now.",
|
|
author: "Chinese Proverb",
|
|
language: "en",
|
|
tags: ["motivation", "wisdom", "work"],
|
|
},
|
|
{
|
|
text: "Do what you can, with what you have, where you are.",
|
|
author: "Theodore Roosevelt",
|
|
language: "en",
|
|
tags: ["motivation", "work", "perseverance"],
|
|
},
|
|
{
|
|
text: "Creativity is intelligence having fun.",
|
|
author: "Albert Einstein",
|
|
language: "en",
|
|
tags: ["creativity", "humor", "wisdom"],
|
|
},
|
|
{
|
|
text: "Everything you can imagine is real.",
|
|
author: "Pablo Picasso",
|
|
language: "en",
|
|
tags: ["creativity", "motivation"],
|
|
},
|
|
{
|
|
text: "I have not failed. I have just found 10,000 ways that will not work.",
|
|
author: "Thomas Edison",
|
|
language: "en",
|
|
tags: ["perseverance", "humor", "success"],
|
|
},
|
|
{
|
|
text: "Well done is better than well said.",
|
|
author: "Benjamin Franklin",
|
|
language: "en",
|
|
tags: ["work", "motivation", "success"],
|
|
},
|
|
{
|
|
text: "You miss 100% of the shots you do not take.",
|
|
author: "Wayne Gretzky",
|
|
language: "en",
|
|
tags: ["motivation", "success"],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* All unique tags available across the local quotes collection.
|
|
*/
|
|
export const AVAILABLE_QUOTE_TAGS: string[] = Array.from(
|
|
new Set(LOCAL_QUOTES.flatMap((q) => q.tags))
|
|
).sort();
|
|
|
|
/**
|
|
* Returns a random quote from the local collection, optionally filtered
|
|
* by language and/or tag.
|
|
*
|
|
* @param language - Filter by "de" or "en". If omitted, picks from all.
|
|
* @param tag - Filter by a specific tag (e.g. "motivation"). If omitted, no tag filter.
|
|
* @returns A random LocalQuote matching the filters, or a fallback if no match found.
|
|
*/
|
|
export function getRandomLocalQuote(
|
|
language?: string,
|
|
tag?: string
|
|
): LocalQuote {
|
|
let pool = LOCAL_QUOTES;
|
|
|
|
if (language) {
|
|
pool = pool.filter((q) => q.language === language);
|
|
}
|
|
|
|
if (tag) {
|
|
pool = pool.filter((q) => q.tags.includes(tag));
|
|
}
|
|
|
|
if (pool.length === 0) {
|
|
// Fallback: return a random quote from the full collection
|
|
return LOCAL_QUOTES[Math.floor(Math.random() * LOCAL_QUOTES.length)];
|
|
}
|
|
|
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
}
|