@@ -13,74 +13,6 @@ enum SortOption: String, CaseIterable {
13
13
case publishedAt = " Newest "
14
14
}
15
15
16
- //struct SearchView: View {
17
- // @Environment(\.modelContext) var modelContext
18
- // @Query(sort: \Search.timestamp, order: .reverse) var searchHistory: [Search]
19
- // @State var query: String = ""
20
- // @State var articles: [NewsArticle] = []
21
- // @State var isLoading = false
22
- // @State var errorMessage: String?
23
- // @State var selectedSortOption: SortOption = .relevance
24
- //
25
- // var body: some View {
26
- // NavigationStack {
27
- // VStack {
28
- // HStack {
29
- // ForEach(SortOption.allCases, id: \.self) { option in
30
- // Button(action: {
31
- // selectedSortOption = option
32
- // sortArticles()
33
- // }) {
34
- // Text(option.rawValue)
35
- // .padding()
36
- // .background(selectedSortOption == option ? Color.blue : Color.gray.opacity(0.3))
37
- // .foregroundStyle(.white)
38
- // .clipShape(RoundedRectangle(cornerRadius: 8))
39
- // }
40
- // }
41
- // }
42
- // .padding()
43
- //
44
- // if isLoading || errorMessage != nil {
45
- // ZStack {
46
- // if isLoading {
47
- // ProgressView("Loading articles")
48
- // .controlSize(.large)
49
- // .tint(.blue)
50
- // } else if let errorMessage = errorMessage {
51
- // Text(errorMessage)
52
- // .foregroundStyle(.red)
53
- // }
54
- // }
55
- // .frame(maxWidth: .infinity)
56
- // .padding()
57
- //
58
- // } else {
59
- // List(articles, id: \.url) { article in
60
- // NavigationLink(destination: ArticleDetailView(article: article)) {
61
- // VStack(alignment: .leading) {
62
- // Text(article.title)
63
- // .font(.headline)
64
- // Text(article.description ?? "No description available")
65
- // .font(.subheadline)
66
- // .foregroundStyle(.secondary)
67
- // }
68
- // }
69
- // }
70
- // }
71
- // }
72
- // .navigationTitle("Search for anything...")
73
- // .searchable(text: $query, placement: .toolbar, prompt: "Search for articles")
74
- // .onChange(of: query) { oldValue, newValue in
75
- // if newValue.isEmpty {
76
- // articles = []
77
- // } else {
78
- // performSearch()
79
- // }
80
- // }
81
- // }
82
- // }
83
-
84
16
struct SearchView : View {
85
17
@Environment ( \. modelContext) var modelContext
86
18
@Query ( sort: \Search . timestamp, order: . reverse) var searchHistory : [ Search ]
@@ -93,8 +25,42 @@ struct SearchView: View {
93
25
var body : some View {
94
26
NavigationStack {
95
27
ZStack {
96
- // Hovedinnholdet i grensesnittet
97
28
VStack {
29
+ HStack {
30
+ TextField ( " Search for articles " , text: $query, onCommit: {
31
+ performSearch ( )
32
+ } )
33
+ . textFieldStyle ( RoundedBorderTextFieldStyle ( ) )
34
+
35
+ if !searchHistory. isEmpty {
36
+ Menu {
37
+ ForEach ( searchHistory) { search in
38
+ Button ( action: {
39
+ query = search. query
40
+ performSearch ( )
41
+ } ) {
42
+ Text ( search. query)
43
+ }
44
+ }
45
+ Button ( action: clearSearchHistory) {
46
+ HStack {
47
+ Text ( " Clear History " )
48
+ . font ( . headline)
49
+ Spacer ( )
50
+ Image ( systemName: " trash " )
51
+ . foregroundStyle ( . red)
52
+ }
53
+ . padding ( 8 )
54
+ }
55
+ } label: {
56
+ Image ( systemName: " arrowtriangle.down.circle " )
57
+ . foregroundColor ( . blue)
58
+ . imageScale ( . large)
59
+ }
60
+ }
61
+ }
62
+ . padding ( )
63
+
98
64
HStack {
99
65
ForEach ( SortOption . allCases, id: \. self) { option in
100
66
Button ( action: {
@@ -123,8 +89,6 @@ struct SearchView: View {
123
89
}
124
90
}
125
91
}
126
-
127
- // Overlay for ProgressView og feilmelding
128
92
if isLoading || errorMessage != nil {
129
93
VStack {
130
94
if isLoading {
@@ -139,22 +103,16 @@ struct SearchView: View {
139
103
}
140
104
}
141
105
. frame ( maxWidth: . infinity, maxHeight: . infinity)
142
- . background ( Color . black. opacity ( 0.4 ) ) // Gjør bakgrunnen semi-transparent
106
+ . background ( Color . black. opacity ( 0.4 ) )
143
107
. edgesIgnoringSafeArea ( . all)
144
108
}
145
109
}
146
- . navigationTitle ( " Search for anything... " )
147
- . searchable ( text: $query, placement: . toolbar, prompt: " Search for articles " )
148
- . onChange ( of: query) { oldValue, newValue in
149
- if newValue. isEmpty {
150
- articles = [ ]
151
- } else {
152
- performSearch ( )
153
- }
154
- }
110
+ . navigationTitle ( " Search " )
155
111
}
156
112
}
157
113
114
+
115
+
158
116
func search( ) {
159
117
guard !query. isEmpty else { return }
160
118
@@ -189,6 +147,9 @@ struct SearchView: View {
189
147
190
148
func performSearch( ) {
191
149
guard !query. isEmpty else { return }
150
+
151
+ saveSearch ( query)
152
+
192
153
isLoading = true
193
154
errorMessage = nil
194
155
@@ -205,9 +166,33 @@ struct SearchView: View {
205
166
}
206
167
}
207
168
}
169
+
170
+ func saveSearch( _ query: String ) {
171
+ if searchHistory. contains ( where: { $0. query == query } ) {
172
+ return
173
+ }
174
+ let newSearch = Search ( query: query)
175
+ modelContext. insert ( newSearch)
176
+ do {
177
+ try modelContext. save ( )
178
+ print ( " Search saved: ' \( query) '. " )
179
+ } catch {
180
+ print ( " Error saving search: \( error) " )
181
+ }
182
+ }
183
+ func clearSearchHistory( ) {
184
+ for search in searchHistory {
185
+ modelContext. delete ( search)
186
+ }
187
+ do {
188
+ try modelContext. save ( )
189
+ print ( " Search history cleared. " )
190
+ } catch {
191
+ print ( " Error clearing search history: \( error) " )
192
+ }
193
+ }
208
194
}
209
195
210
196
#Preview {
211
197
SearchView ( )
212
198
}
213
-
0 commit comments