1
- document . addEventListener ( 'DOMContentLoaded' , ( ) => {
2
- async function fetchQuotes ( ) {
3
- try {
4
- const response = await fetch ( 'quotes.json' ) ;
5
- return await response . json ( ) ;
6
- } catch ( error ) {
7
- console . error ( 'Error loading quotes:' , error ) ;
8
- return [ ] ;
9
- }
10
- }
1
+ document . addEventListener ( 'DOMContentLoaded' , async ( ) => {
2
+ let quotes = [ ] ;
3
+ let currentQuote = null ;
4
+ const favorites = JSON . parse ( localStorage . getItem ( 'favoriteQuotes' ) || '[]' ) ;
11
5
12
6
const quoteText = document . getElementById ( 'quote-text' ) ;
13
7
const quoteAuthor = document . getElementById ( 'quote-author' ) ;
14
8
const quoteCategory = document . getElementById ( 'quote-category' ) ;
15
9
const notification = document . getElementById ( 'notification' ) ;
10
+ const favoritesList = document . getElementById ( 'favorites-list' ) ;
16
11
17
- function showNotification ( message ) {
12
+ function showNotification ( message , isError = false ) {
18
13
notification . textContent = message ;
14
+ notification . className = isError ? 'error-message' : '' ;
19
15
notification . style . display = 'block' ;
20
16
setTimeout ( ( ) => {
21
17
notification . style . display = 'none' ;
22
18
} , 2000 ) ;
23
19
}
24
20
21
+ async function fetchQuotes ( ) {
22
+ try {
23
+ const response = await fetch ( 'quotes.json' ) ;
24
+ if ( ! response . ok ) {
25
+ throw new Error ( 'Failed to load quotes' ) ;
26
+ }
27
+ quotes = await response . json ( ) ;
28
+ } catch ( error ) {
29
+ console . error ( 'Error loading quotes:' , error ) ;
30
+ showNotification ( 'Error loading quotes. Please try again later.' , true ) ;
31
+ quotes = [ ] ;
32
+ }
33
+ }
34
+
25
35
async function loadQuote ( ) {
26
- const quotes = await fetchQuotes ( ) ;
27
- if ( quotes && quotes . length > 0 ) {
28
- const randomQuote = quotes [ Math . floor ( Math . random ( ) * quotes . length ) ] ;
29
- quoteText . textContent = `"${ randomQuote . Quote } "` ;
30
- quoteAuthor . textContent = `- ${ randomQuote . Author } ` ;
31
- quoteCategory . textContent = `Category: ${ randomQuote . Category } ` ;
36
+ if ( quotes . length === 0 ) {
37
+ await fetchQuotes ( ) ;
38
+ }
39
+
40
+ if ( quotes . length > 0 ) {
41
+ currentQuote = quotes [ Math . floor ( Math . random ( ) * quotes . length ) ] ;
42
+ quoteText . textContent = `"${ currentQuote . Quote } "` ;
43
+ quoteAuthor . textContent = `- ${ currentQuote . Author } ` ;
44
+ quoteCategory . textContent = `Category: ${ currentQuote . Category } ` ;
32
45
}
33
46
}
34
47
35
- loadQuote ( ) ;
48
+ function updateFavoritesList ( ) {
49
+ favoritesList . innerHTML = '' ;
50
+ favorites . forEach ( ( quote , index ) => {
51
+ const quoteElement = document . createElement ( 'div' ) ;
52
+ quoteElement . className = 'favorite-quote' ;
53
+ quoteElement . innerHTML = `
54
+ <p class="favorite-quote-text">"${ quote . Quote } "</p>
55
+ <p class="favorite-quote-author">- ${ quote . Author } </p>
56
+ <button class="remove-favorite" data-index="${ index } ">
57
+ <i class="fas fa-times"></i>
58
+ </button>
59
+ ` ;
60
+ favoritesList . appendChild ( quoteElement ) ;
61
+ } ) ;
62
+
63
+ const favoriteCount = document . querySelector ( '.favorite-count' ) ;
64
+ favoriteCount . textContent = favorites . length ;
65
+
66
+ document . querySelectorAll ( '.remove-favorite' ) . forEach ( button => {
67
+ button . addEventListener ( 'click' , ( e ) => {
68
+ const index = parseInt ( e . currentTarget . dataset . index ) ;
69
+ favorites . splice ( index , 1 ) ;
70
+ localStorage . setItem ( 'favoriteQuotes' , JSON . stringify ( favorites ) ) ;
71
+ updateFavoritesList ( ) ;
72
+ showNotification ( 'Quote removed from favorites!' ) ;
73
+ } ) ;
74
+ } ) ;
75
+ }
76
+
77
+ const toggleTheme = document . getElementById ( 'toggle-theme' ) ;
78
+ const prefersDarkScheme = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
79
+
80
+ if ( prefersDarkScheme . matches ) {
81
+ document . body . classList . add ( 'dark-mode' ) ;
82
+ }
83
+
84
+ toggleTheme . addEventListener ( 'click' , ( ) => {
85
+ document . body . classList . toggle ( 'dark-mode' ) ;
86
+ } ) ;
87
+
88
+ const toggleFavoritesBtn = document . getElementById ( 'toggle-favorites' ) ;
89
+ const favoritesContainer = document . querySelector ( '.favorites-container' ) ;
90
+
91
+ toggleFavoritesBtn . addEventListener ( 'click' , ( ) => {
92
+ const isVisible = favoritesContainer . classList . contains ( 'visible' ) ;
93
+ favoritesContainer . classList . toggle ( 'visible' ) ;
94
+ toggleFavoritesBtn . classList . toggle ( 'active' ) ;
95
+
96
+ const icon = toggleFavoritesBtn . querySelector ( 'i' ) ;
97
+ icon . className = isVisible ? 'fas fa-heart' : 'fas fa-times' ;
98
+ } ) ;
99
+
100
+ await loadQuote ( ) ;
101
+ updateFavoritesList ( ) ;
36
102
37
103
document . getElementById ( 'new-quote' ) . addEventListener ( 'click' , loadQuote ) ;
38
104
@@ -42,5 +108,27 @@ document.addEventListener('DOMContentLoaded', () => {
42
108
showNotification ( 'Quote copied to clipboard!' ) ;
43
109
} ) ;
44
110
} ) ;
45
- } ) ;
46
111
112
+ document . getElementById ( 'favorite-quote' ) . addEventListener ( 'click' , ( ) => {
113
+ if ( ! currentQuote ) return ;
114
+
115
+ const quoteExists = favorites . some ( q => q . Quote === currentQuote . Quote ) ;
116
+
117
+ if ( quoteExists ) {
118
+ showNotification ( 'Quote already in favorites!' , true ) ;
119
+ return ;
120
+ }
121
+
122
+ favorites . push ( currentQuote ) ;
123
+ localStorage . setItem ( 'favoriteQuotes' , JSON . stringify ( favorites ) ) ;
124
+ updateFavoritesList ( ) ;
125
+ showNotification ( 'Quote added to favorites!' ) ;
126
+
127
+ if ( favorites . length === 1 ) {
128
+ favoritesContainer . classList . add ( 'visible' ) ;
129
+ toggleFavoritesBtn . classList . add ( 'active' ) ;
130
+ const icon = toggleFavoritesBtn . querySelector ( 'i' ) ;
131
+ icon . className = 'fas fa-times' ;
132
+ }
133
+ } ) ;
134
+ } ) ;
0 commit comments