Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungI audited my own ML linter and had to withdraw its best evidence(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungQuantum Result Validation for Distributed Computing Systems(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungJWT Authentication and Role-Based Access Control in LocalHands(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungStochastic Parrot or Alien Mind?(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungBuilding AI for the Physical World Is a Different Engineering Problem(21.09.2026 um 22:58 Uhr)
Sichere ProgrammierungI audited my own ML linter and had to withdraw its best evidence(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungQuantum Result Validation for Distributed Computing Systems(21.09.2026 um 22:54 Uhr)
Sichere ProgrammierungJWT Authentication and Role-Based Access Control in LocalHands(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungStochastic Parrot or Alien Mind?(21.09.2026 um 22:56 Uhr)
Sichere ProgrammierungBuilding AI for the Physical World Is a Different Engineering Problem(21.09.2026 um 22:58 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Part 5 — Deals, pricing, and a real board

Part 5 — Deals, pricing, and a real board Level: Intermediate/Advanced · Time: ~35 minutes · Builds on: Part 4 — Tags, ratings, and richer rows · Series 2, Part 2 of 3 Your contacts are tagged and scored. Now give them money attached —…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




Part 5 — Deals, pricing, and a real board




Level: Intermediate/Advanced · Time: ~35 minutes · Builds on: Part 4 — Tags, ratings, and richer rows · Series 2, Part 2 of 3




Your contacts are tagged and scored. Now give them money attached — a deal value, a quote with real line items, and a board to see all of it at once. By the end of this tutorial your Contacts app will, without exaggeration, be doing the job of a lightweight sales pipeline.



Keep that thought. We'll come back to it in Part 6.









What we're adding




  1. A Deal model attached to each contact, with a stage and a value.


  2. DFPriceView and DFPriceSummaryView — a real quote screen with subtotal, discount, tax, and total.


  3. DFQuantityStepper — editable line-item quantities on that quote.

  4. A deals board — DFGrid of DFEntityCards, grouped by stage, filtered with the DFChip row from Part 4.


  5. DFCarousel — a "hot leads" horizontal rail on the dashboard.









1. The Deal model






enum DealStage: String, CaseIterable, Identifiable, Hashable {
case new, qualified, proposal, won
var id: String { rawValue }
var label: String {
switch self {
case .new: "New"
case .qualified: "Qualified"
case .proposal: "Proposal"
case .won: "Won"
}
}
}

struct LineItem: Identifiable, Hashable {
let id = UUID()
var name: String
var unitPrice: Decimal
var quantity: Int = 1
var lineTotal: Decimal { unitPrice * Decimal(quantity) }
}

struct Deal: Identifiable, Hashable {
let id = UUID()
var contactID: Contact.ID
var title: String
var stage: DealStage = .new
var lineItems: [LineItem]
var value: Decimal { lineItems.reduce(0) { $0 + $1.lineTotal } }
}












2. A quote screen — DFPriceView, DFQuantityStepper, DFPriceSummaryView



Three components, one screen, in the order a user actually reads a quote: line items with editable quantities, then a summary breakdown at the bottom.




struct QuoteView: View {
@State var deal: Deal
private let taxRate: Decimal = 0.08

private var subtotal: Decimal { deal.lineItems.reduce(0) { $0 + $1.lineTotal } }
private var tax: Decimal { subtotal * taxRate }

var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
DFCard {
VStack(alignment: .leading, spacing: 12) {
DFText("Line items", scale: .headline)
ForEach($deal.lineItems) { $item in
HStack {
VStack(alignment: .leading, spacing: 2) {
DFText(item.name, scale: .body)
DFPriceView(amount: item.unitPrice).dfPriceViewStyle(.compact)
}
Spacer()
DFQuantityStepper(value: $item.quantity, range: 1...20)
.dfQuantityStepperStyle(.compact)
}
}
}
}

DFCard {
DFPriceSummaryView(lineItems: [
DFPriceLineItem(label: "Subtotal", amount: subtotal),
DFPriceLineItem(label: "Tax (8%)", amount: tax),
DFPriceLineItem(label: "Total", amount: subtotal + tax, emphasis: .total),
])
}
}
.padding()
}
.dfNavigationBar(title: deal.title) { }
}
}






Worth calling out:





  • DFPriceView(amount:) formats currency for you via Decimal.formatted(.currency(code:)) — locale-aware, no manual NumberFormatter. Pass compareAtAmount: and it renders a strikethrough automatically — handy for showing a discounted line item.


  • DFQuantityStepper is named that, not DFStepper, specifically to avoid colliding with SwiftUI's own Stepper. .compact style keeps it tight enough to live inline in a row like this.


  • DFPriceSummaryView takes an array of DFPriceLineItems — emphasis: .total on the last one renders a divider above it and bumps it to a headline weight automatically. You don't hand-roll the "is this the total row" styling logic.




Pro moment. Pro's E-commerce vertical ships this exact quote/checkout pattern already wired to real order data, plus a revenue dashboard built on the same DFPriceView primitive. If quotes and invoices are core to your product, that's a screen you don't write twice.










3. A deals board with DFGrid



Group deals by stage, reuse the segment-filter chip row's pattern for stage filtering, and lay the results out in a grid of DFEntityCards.




struct DealsBoardView: View {
let deals: [Deal]
@State private var selectedStage: DealStage?

private var visible: [Deal] {
guard let selectedStage else { return deals }
return deals.filter { $0.stage == selectedStage }
}

var body: some View {
VStack(spacing: 0) {
HStack(spacing: 8) {
DFChip(.selectable("All"), isSelected: selectedStage == nil)
.onTapGesture { selectedStage = nil }
ForEach(DealStage.allCases) { stage in
DFChip(.selectable(stage.label), isSelected: selectedStage == stage)
.onTapGesture { selectedStage = stage }
}
}
.padding()

ScrollView {
if visible.isEmpty {
DFEmptyState(icon: "briefcase", title: "No deals in this stage")
.padding(.top, 40)
} else {
DFGrid(columns: .adaptive(minWidth: 200)) {
ForEach(visible) { deal in
DFEntityCard(
media: .systemImage("briefcase.fill"),
title: deal.title,
subtitle: DFPriceView.formattedAmount(deal.value, currencyCode: "USD"),
trailing: .badge(deal.stage.label)
)
}
}
.padding()
}
}
}
.dfNavigationBar(title: "Deals") { }
}
}






DFGrid(columns: .adaptive(minWidth: 200)) reflows automatically — three cards wide on an iPhone in landscape, six on a Mac window, one on a compact iPhone portrait — with zero size-class branching in this view.









4. A "hot leads" rail with DFCarousel



A dashboard strip showing your highest-scoring leads, horizontally scrollable, no paging ceremony required.




struct HotLeadsRail: View {
let contacts: [Contact] // pre-sorted by relationshipScore, highest first

var body: some View {
VStack(alignment: .leading, spacing: 8) {
DFText("Hot leads", scale: .headline).padding(.horizontal)
DFCarousel {
ForEach(contacts.prefix(8)) { contact in
DFEntityCard(
media: .avatarInitials(contact.initials),
title: contact.name,
subtitle: contact.role
)
.frame(width: 140)
}
}
.padding(.horizontal)
}
}
}






DFCarousel is deliberately a plain themed ScrollView wrapper — no built-in page indicator or snap-to-page behavior. If you need true paging, compose your own TabView(.page); for a "scroll and glance" rail like this one, the simpler primitive is the right tool.









What you built




  • A Deal model with a stage and computed value.

  • A quote screen combining editable line items, a quantity stepper, and an automatic subtotal/tax/total breakdown.

  • A filterable deals board reflowing across screen sizes with zero manual breakpoints.

  • A horizontally scrolling "hot leads" rail on the dashboard.



Stop for a second: you now have contacts, segments, relationship scores, deals, a priced quote screen, and a filterable board. That's not a demo anymore.









Coming in Part 6



The last tutorial in this series isn't about a new component — it's about when and how to tell the user "you don't have to keep building this." We'll add a real, well-placed DFBanner, use DFEmptyState's new secondary action for an honest upgrade prompt, and put your hand-built board side-by-side with what Pro's CRM vertical ships on day one.



Part 6 — Nudge, prompt, and know when to buy









What Pro already has here



Pipeline boards, quote screens, and lead-scoring dashboards are exactly what DesignFoundationPro's CRM and E-commerce verticals ship — pre-wired, with CRMPreviewFixtures/DFEcommercePreviewFixtures standing in for your real data until you swap it. You just wrote a smaller version of both by hand. That's useful to know before your next project, not just this one.



DesignFoundation Pro

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Part 5 — Deals, pricing, and a real board

Thematisch verwandte Begriffe: Part, Deals, pricing, real · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-45381 | Tautulli is a Python based monitoring and tracking tool for Plex Media S…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick