Просмотр исходного кода

Replace insights card with wide search bar on dashboard.

Remove profile insights fields from DashboardData. Add a centered search field with icon and placeholder; width follows the main overlay at 82% instead of a fixed width.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 недель назад: 3
Родитель
Сommit
528d160db1
2 измененных файлов с 55 добавлено и 74 удалено
  1. 1 5
      App for Indeed/Models/DashboardModels.swift
  2. 54 69
      App for Indeed/Views/DashboardView.swift

+ 1 - 5
App for Indeed/Models/DashboardModels.swift

@@ -14,8 +14,6 @@ struct SidebarItem {
14
 struct DashboardData {
14
 struct DashboardData {
15
     let subtitle: String
15
     let subtitle: String
16
     let sidebarItems: [SidebarItem]
16
     let sidebarItems: [SidebarItem]
17
-    let profileInsightsTitle: String
18
-    let profileInsightsBody: String
19
 }
17
 }
20
 
18
 
21
 protocol DashboardDataProviding {
19
 protocol DashboardDataProviding {
@@ -32,9 +30,7 @@ final class MockDashboardDataProvider: DashboardDataProviding {
32
                 SidebarItem(title: "Interviews", systemImage: "list.bullet", badge: nil),
30
                 SidebarItem(title: "Interviews", systemImage: "list.bullet", badge: nil),
33
                 SidebarItem(title: "Profile", systemImage: "person", badge: nil),
31
                 SidebarItem(title: "Profile", systemImage: "person", badge: nil),
34
                 SidebarItem(title: "Settings", systemImage: "gearshape", badge: nil)
32
                 SidebarItem(title: "Settings", systemImage: "gearshape", badge: nil)
35
-            ],
36
-            profileInsightsTitle: "AI insights",
37
-            profileInsightsBody: "Saved jobs and interviews at a glance."
33
+            ]
38
         )
34
         )
39
     }
35
     }
40
 }
36
 }

+ 54 - 69
App for Indeed/Views/DashboardView.swift

@@ -32,12 +32,9 @@ final class DashboardView: NSView {
32
     private let mainOverlay = NSStackView()
32
     private let mainOverlay = NSStackView()
33
     private let greetingLabel = NSTextField(labelWithString: "")
33
     private let greetingLabel = NSTextField(labelWithString: "")
34
     private let subtitleLabel = NSTextField(labelWithString: "")
34
     private let subtitleLabel = NSTextField(labelWithString: "")
35
-    private let insightsCard = NSView()
36
-    private let insightsTitleLabel = NSTextField(labelWithString: "")
37
-    private let insightsBodyLabel = NSTextField(labelWithString: "")
38
-    private let togglesLabel = NSTextField(labelWithString: "Show:")
39
-    private let savedToggleButton = NSButton(title: "Saved", target: nil, action: nil)
40
-    private let interviewsToggleButton = NSButton(title: "Interviews", target: nil, action: nil)
35
+    private let searchCard = NSView()
36
+    private let searchIcon = NSImageView()
37
+    private let searchField = NSTextField()
41
     private let sparkleView = NSImageView()
38
     private let sparkleView = NSImageView()
42
     private let scrollView = NSScrollView()
39
     private let scrollView = NSScrollView()
43
 
40
 
@@ -59,8 +56,6 @@ final class DashboardView: NSView {
59
     func render(_ data: DashboardData) {
56
     func render(_ data: DashboardData) {
60
         greetingLabel.stringValue = "Welcome"
57
         greetingLabel.stringValue = "Welcome"
61
         subtitleLabel.stringValue = data.subtitle
58
         subtitleLabel.stringValue = data.subtitle
62
-        insightsTitleLabel.stringValue = data.profileInsightsTitle
63
-        insightsBodyLabel.stringValue = data.profileInsightsBody
64
         configureSidebar(data.sidebarItems)
59
         configureSidebar(data.sidebarItems)
65
         updateDocumentLayout()
60
         updateDocumentLayout()
66
     }
61
     }
@@ -130,7 +125,7 @@ final class DashboardView: NSView {
130
         topInset.translatesAutoresizingMaskIntoConstraints = false
125
         topInset.translatesAutoresizingMaskIntoConstraints = false
131
         topInset.heightAnchor.constraint(equalToConstant: 32).isActive = true
126
         topInset.heightAnchor.constraint(equalToConstant: 32).isActive = true
132
 
127
 
133
-        configureInsightsCard()
128
+        configureSearchCard()
134
 
129
 
135
         let titleBlock = NSStackView(views: [greetingLabel, subtitleLabel])
130
         let titleBlock = NSStackView(views: [greetingLabel, subtitleLabel])
136
         titleBlock.orientation = .vertical
131
         titleBlock.orientation = .vertical
@@ -149,7 +144,7 @@ final class DashboardView: NSView {
149
         mainOverlay.addArrangedSubview(topInset)
144
         mainOverlay.addArrangedSubview(topInset)
150
         mainOverlay.addArrangedSubview(titleBlock)
145
         mainOverlay.addArrangedSubview(titleBlock)
151
         mainOverlay.addArrangedSubview(midSpacer)
146
         mainOverlay.addArrangedSubview(midSpacer)
152
-        mainOverlay.addArrangedSubview(insightsCard)
147
+        mainOverlay.addArrangedSubview(searchCard)
153
         mainOverlay.addArrangedSubview(overlayBottomSpacer)
148
         mainOverlay.addArrangedSubview(overlayBottomSpacer)
154
 
149
 
155
         sparkleView.translatesAutoresizingMaskIntoConstraints = false
150
         sparkleView.translatesAutoresizingMaskIntoConstraints = false
@@ -185,6 +180,8 @@ final class DashboardView: NSView {
185
             mainOverlay.topAnchor.constraint(equalTo: mainHost.topAnchor),
180
             mainOverlay.topAnchor.constraint(equalTo: mainHost.topAnchor),
186
             mainOverlay.bottomAnchor.constraint(equalTo: mainHost.bottomAnchor, constant: -24),
181
             mainOverlay.bottomAnchor.constraint(equalTo: mainHost.bottomAnchor, constant: -24),
187
 
182
 
183
+            searchCard.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.82),
184
+
188
             greetingLabel.leadingAnchor.constraint(equalTo: mainOverlay.leadingAnchor, constant: 24),
185
             greetingLabel.leadingAnchor.constraint(equalTo: mainOverlay.leadingAnchor, constant: 24),
189
             greetingLabel.trailingAnchor.constraint(equalTo: mainOverlay.trailingAnchor, constant: -24),
186
             greetingLabel.trailingAnchor.constraint(equalTo: mainOverlay.trailingAnchor, constant: -24),
190
             subtitleLabel.leadingAnchor.constraint(equalTo: greetingLabel.leadingAnchor),
187
             subtitleLabel.leadingAnchor.constraint(equalTo: greetingLabel.leadingAnchor),
@@ -195,70 +192,58 @@ final class DashboardView: NSView {
195
         ])
192
         ])
196
     }
193
     }
197
 
194
 
198
-    private func configureInsightsCard() {
199
-        insightsCard.wantsLayer = true
200
-        insightsCard.layer?.backgroundColor = Theme.cardBackground.cgColor
201
-        insightsCard.layer?.cornerRadius = 18
202
-        insightsCard.translatesAutoresizingMaskIntoConstraints = false
203
-
204
-        insightsTitleLabel.font = .systemFont(ofSize: 20, weight: .semibold)
205
-        insightsTitleLabel.textColor = Theme.primaryText
206
-        insightsTitleLabel.alignment = .center
207
-        insightsTitleLabel.maximumNumberOfLines = 1
208
-
209
-        insightsBodyLabel.font = .systemFont(ofSize: 13, weight: .regular)
210
-        insightsBodyLabel.textColor = Theme.secondaryText
211
-        insightsBodyLabel.alignment = .center
212
-        insightsBodyLabel.maximumNumberOfLines = 4
213
-        insightsBodyLabel.lineBreakMode = .byWordWrapping
214
-        insightsBodyLabel.preferredMaxLayoutWidth = 400
215
-
216
-        togglesLabel.font = .systemFont(ofSize: 12, weight: .medium)
217
-        togglesLabel.textColor = Theme.tertiaryText
218
-        togglesLabel.alignment = .center
219
-        togglesLabel.maximumNumberOfLines = 1
220
-
221
-        styleToggle(savedToggleButton)
222
-        styleToggle(interviewsToggleButton)
223
-
224
-        let toggleRow = NSStackView(views: [savedToggleButton, interviewsToggleButton])
225
-        toggleRow.orientation = .horizontal
226
-        toggleRow.spacing = 10
227
-        toggleRow.alignment = .centerY
228
-
229
-        let inner = NSStackView(views: [
230
-            insightsTitleLabel,
231
-            insightsBodyLabel,
232
-            togglesLabel,
233
-            toggleRow
234
-        ])
235
-        inner.orientation = .vertical
236
-        inner.spacing = 10
237
-        inner.alignment = .centerX
238
-        inner.distribution = .fill
239
-        inner.translatesAutoresizingMaskIntoConstraints = false
195
+    private func configureSearchCard() {
196
+        searchCard.wantsLayer = true
197
+        searchCard.layer?.backgroundColor = Theme.cardBackground.cgColor
198
+        searchCard.layer?.cornerRadius = 14
199
+        searchCard.layer?.borderWidth = 1
200
+        searchCard.layer?.borderColor = NSColor(calibratedWhite: 1, alpha: 0.06).cgColor
201
+        searchCard.translatesAutoresizingMaskIntoConstraints = false
202
+        searchCard.setContentHuggingPriority(.defaultHigh, for: .vertical)
203
+
204
+        searchIcon.translatesAutoresizingMaskIntoConstraints = false
205
+        searchIcon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 15, weight: .medium)
206
+        searchIcon.image = NSImage(systemSymbolName: "magnifyingglass", accessibilityDescription: "Search")
207
+        searchIcon.contentTintColor = Theme.secondaryText
208
+
209
+        searchField.translatesAutoresizingMaskIntoConstraints = false
210
+        searchField.isBordered = false
211
+        searchField.drawsBackground = false
212
+        searchField.focusRingType = .none
213
+        searchField.font = .systemFont(ofSize: 14, weight: .regular)
214
+        searchField.textColor = Theme.primaryText
215
+        searchField.placeholderAttributedString = NSAttributedString(
216
+            string: "Search jobs, companies, or locations",
217
+            attributes: [
218
+                .foregroundColor: Theme.tertiaryText,
219
+                .font: NSFont.systemFont(ofSize: 14, weight: .regular)
220
+            ]
221
+        )
222
+        searchField.cell?.usesSingleLineMode = true
223
+        searchField.cell?.wraps = false
224
+        searchField.cell?.isScrollable = true
225
+        searchField.target = self
226
+        searchField.action = #selector(didSubmitSearch)
227
+
228
+        searchCard.addSubview(searchIcon)
229
+        searchCard.addSubview(searchField)
240
 
230
 
241
-        insightsCard.setContentHuggingPriority(.defaultHigh, for: .vertical)
242
-        insightsCard.addSubview(inner)
243
         NSLayoutConstraint.activate([
231
         NSLayoutConstraint.activate([
244
-            inner.leadingAnchor.constraint(equalTo: insightsCard.leadingAnchor, constant: 32),
245
-            inner.trailingAnchor.constraint(equalTo: insightsCard.trailingAnchor, constant: -32),
246
-            inner.topAnchor.constraint(equalTo: insightsCard.topAnchor, constant: 22),
247
-            inner.bottomAnchor.constraint(equalTo: insightsCard.bottomAnchor, constant: -22),
248
-            insightsCard.widthAnchor.constraint(equalToConstant: 440)
232
+            searchCard.heightAnchor.constraint(equalToConstant: 48),
233
+
234
+            searchIcon.leadingAnchor.constraint(equalTo: searchCard.leadingAnchor, constant: 16),
235
+            searchIcon.centerYAnchor.constraint(equalTo: searchCard.centerYAnchor),
236
+            searchIcon.widthAnchor.constraint(equalToConstant: 18),
237
+            searchIcon.heightAnchor.constraint(equalToConstant: 18),
238
+
239
+            searchField.leadingAnchor.constraint(equalTo: searchIcon.trailingAnchor, constant: 10),
240
+            searchField.trailingAnchor.constraint(equalTo: searchCard.trailingAnchor, constant: -16),
241
+            searchField.centerYAnchor.constraint(equalTo: searchCard.centerYAnchor)
249
         ])
242
         ])
250
     }
243
     }
251
 
244
 
252
-    private func styleToggle(_ button: NSButton) {
253
-        button.bezelStyle = .rounded
254
-        button.font = .systemFont(ofSize: 12, weight: .medium)
255
-        button.contentTintColor = Theme.secondaryText
256
-        button.wantsLayer = true
257
-        button.layer?.backgroundColor = Theme.toggleBackground.cgColor
258
-        button.layer?.cornerRadius = 8
259
-        button.translatesAutoresizingMaskIntoConstraints = false
260
-        button.widthAnchor.constraint(equalToConstant: 108).isActive = true
261
-        button.heightAnchor.constraint(equalToConstant: 30).isActive = true
245
+    @objc private func didSubmitSearch() {
246
+        // Hook up search submission here when wiring up real data.
262
     }
247
     }
263
 
248
 
264
     private func configureSidebar(_ items: [SidebarItem]) {
249
     private func configureSidebar(_ items: [SidebarItem]) {