Selaa lähdekoodia

Fix job search results visibility and simplify assistant response.

Render the listings scroll section in the main layout so result cards appear after search, and replace verbose row/JSON chat output with a concise card-focused summary.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 3 viikkoa sitten
vanhempi
commit
a57976258d
1 muutettua tiedostoa jossa 8 lisäystä ja 32 poistoa
  1. 8 32
      App for Indeed/Views/DashboardView.swift

+ 8 - 32
App for Indeed/Views/DashboardView.swift

@@ -259,6 +259,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
259 259
         mainOverlay.addArrangedSubview(chatStatusStack)
260 260
         mainOverlay.addArrangedSubview(listingsTopSpacer)
261 261
         mainOverlay.addArrangedSubview(chatScrollView)
262
+        mainOverlay.addArrangedSubview(jobListingsScrollView)
262 263
         mainOverlay.addArrangedSubview(searchBarShadowHost)
263 264
 
264 265
         contentStack.addArrangedSubview(sidebar)
@@ -291,10 +292,12 @@ final class DashboardView: NSView, NSTextFieldDelegate {
291 292
             searchBarShadowHost.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
292 293
             chatStatusStack.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
293 294
             chatScrollView.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
295
+            jobListingsScrollView.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
294 296
 
295 297
             jobListingsContainer.topAnchor.constraint(equalTo: jobListingsScrollView.contentView.topAnchor),
296 298
             jobListingsContainer.leadingAnchor.constraint(equalTo: jobListingsScrollView.contentView.leadingAnchor),
297 299
             jobListingsContainer.widthAnchor.constraint(equalTo: jobListingsScrollView.contentView.widthAnchor),
300
+            jobListingsScrollView.heightAnchor.constraint(greaterThanOrEqualToConstant: 200),
298 301
 
299 302
             greetingLabel.leadingAnchor.constraint(equalTo: mainOverlay.leadingAnchor, constant: 16),
300 303
             greetingLabel.trailingAnchor.constraint(equalTo: mainOverlay.trailingAnchor, constant: -16),
@@ -1209,7 +1212,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1209 1212
                 case .success(let output):
1210 1213
                     let normalizedJobs = self.normalizedJobs(output.jobs)
1211 1214
                     self.configureJobListings(normalizedJobs, noResultsForQuery: prompt)
1212
-                    let reply = self.makeAssistantSearchReply(query: prompt, jobs: normalizedJobs, jsonResult: output.rawJSON)
1215
+                    let reply = self.makeAssistantSearchReply(query: prompt, jobs: normalizedJobs)
1213 1216
                     self.chatMessages.append(ChatMessage(role: "assistant", content: reply))
1214 1217
                     self.appendChatBubble(text: reply, isUser: false)
1215 1218
                     self.chatStatusLabel.stringValue = "Ask for another job, company, or skill match"
@@ -1234,42 +1237,16 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1234 1237
         return trimmed.filter { !$0.title.isEmpty && !$0.description.isEmpty }
1235 1238
     }
1236 1239
 
1237
-    private func makeAssistantSearchReply(query: String, jobs: [JobListing], jsonResult: String) -> String {
1240
+    private func makeAssistantSearchReply(query: String, jobs: [JobListing]) -> String {
1238 1241
         if jobs.isEmpty {
1239
-            return """
1240
-            No jobs were found for "\(query)".
1241
-
1242
-            JSON result:
1243
-            \(jsonResult)
1244
-            """
1245
-        }
1246
-        let rows = jobs.prefix(8).enumerated().map { index, job in
1247
-            let fallback = "https://www.indeed.com/jobs?q=\(job.title.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"
1248
-            let link = (job.url?.isEmpty == false) ? job.url! : fallback
1249
-            let compactDescription = compactSingleLine(job.description, maxCharacters: 110)
1250
-            return "\(index + 1)) \(job.title) | \(compactDescription) | \(link)"
1242
+            return "No jobs were found for \"\(query)\". Try another title, skill, company, or location."
1251 1243
         }
1252 1244
         return """
1253 1245
         Found \(jobs.count) job result(s) for "\(query)".
1254
-
1255
-        Row-wise results:
1256
-        \(rows.joined(separator: "\n"))
1257
-
1258
-        JSON result:
1259
-        \(jsonResult)
1246
+        Each result is shown as a card with the role, job description, and an Apply button that opens the job link.
1260 1247
         """
1261 1248
     }
1262 1249
 
1263
-    private func compactSingleLine(_ text: String, maxCharacters: Int) -> String {
1264
-        let single = text
1265
-            .replacingOccurrences(of: "\n", with: " ")
1266
-            .replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression)
1267
-            .trimmingCharacters(in: .whitespacesAndNewlines)
1268
-        guard single.count > maxCharacters, maxCharacters > 1 else { return single }
1269
-        let end = single.index(single.startIndex, offsetBy: maxCharacters - 1)
1270
-        return String(single[..<end]) + "…"
1271
-    }
1272
-
1273 1250
     func controlTextDidBeginEditing(_ obj: Notification) {
1274 1251
         applySearchFieldInsertionPoint(obj.object)
1275 1252
         if (obj.object as? NSTextField) === jobKeywordsField {
@@ -1665,7 +1642,7 @@ private final class OpenAIJobSearchService {
1665 1642
                 let cleanedText = Self.extractJSONObject(from: text)
1666 1643
                 let jsonData = Data(cleanedText.utf8)
1667 1644
                 let jobsPayload = try JSONDecoder().decode(JobSearchResultsPayload.self, from: jsonData)
1668
-                completion(.success(JobSearchOutput(jobs: jobsPayload.jobs, rawJSON: cleanedText)))
1645
+                completion(.success(JobSearchOutput(jobs: jobsPayload.jobs)))
1669 1646
             } catch {
1670 1647
                 let rawBody = String(data: data, encoding: .utf8) ?? "<non-utf8 response>"
1671 1648
                 let message = "The API response could not be parsed as job JSON. Raw response: \(rawBody.prefix(600))"
@@ -1772,7 +1749,6 @@ private struct JobSearchResultsPayload: Codable {
1772 1749
 
1773 1750
 private struct JobSearchOutput {
1774 1751
     let jobs: [JobListing]
1775
-    let rawJSON: String
1776 1752
 }
1777 1753
 
1778 1754
 private struct OpenAIAPIErrorResponse: Codable {