Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Tables & Lists

Deal Pipeline

Tables & Lists

Deal Pipeline React component for Tailwind CSS v4

Data TableEditable Grid
Live props
Behavior
requireLostReason
persistKey
staleAfterDays14 days
State
defaultView
defaultShowClosed
readOnly
loading
Layout
showSummary
columnWidth288px
Content
showWeighted
compactAmounts
currency
locale
Appearance
cardVariant
size
tone
Code
import { DealPipeline } from "@/components/ui/deal-pipeline"

<DealPipeline />
  1. Home
  2. Components
  3. Tables & Lists
  4. Deal Pipeline
Pro

Deal Pipeline React component for Tailwind CSS v4

v1.0.1·Updated in 1.9.0

A React sales pipeline board: deal stages with weighted totals, a forecast summary, drag between stages with a lost reason, a list view.

The summary on top reads the open pipeline, the weighted forecast, what was won this month and the win rate (a small ring); on a phone it is a 2 x 2 grid that folds to one line ("Pipeline $224,850 · weighted $118,065") with a tap on its chevron. Each stage is a column: its header shows the count and the probability, the line under it the total and the weighted total, and won and lost columns are tinted green and red. Drag a deal with the mouse (after 8px) or a long press on touch (250ms, with a haptic tick) to another stage: while it is lifted its probability bar already grows or shrinks to the stage under it, and on the drop the header totals fade to their new values. Drop it on Lost and a dialog (a bottom sheet on phones) asks why: arrows pick a reason, Enter confirms, the last reason opens a text field (Cmd / Ctrl + Enter confirms from it), Escape or Cancel sends the card back. A deal dropped on Won pops and shows a green check for a moment. While a move saves, the card shows a spinner; if the save fails, the card springs back and the reason is announced. With the keyboard every card is a Tab stop: Space lifts it, arrows move it (Left / Right change stage), Space drops, Escape cancels, Enter opens it, and Shift + F10 or the Menu key opens its ⋯ menu (Move to, Mark as won, Mark as lost and your own actions). The toolbar switches between Board and List (arrows move inside it), filters by owner with avatar chips that toggle (they scroll sideways on a phone) and hides the closed stages with a switch. The list view is a table grouped by stage, with a band per stage and the deal's value, probability, owner, close date and days in stage; rows open on click or Enter, and on a phone every row is a card. Deals past their close date turn red with a crossed calendar, and deals stuck longer than staleAfterDays in a stage get an amber "18 days in stage" chip. On a phone the board shows one stage at a time with the next one peeking and a chip row to jump between stages. Reduced motion drops the pop, the tilt and the growing bars and keeps short fades.

Deal Pipeline is a Pro React component in the React table and list components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add deal-pipeline, together with Avatar, Badge, Button, Dialog, Dropdown Menu and 20 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add deal-pipeline

Deal Pipeline is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import DealPipeline from @/components/ui/deal-pipeline.

import { useState } from "react"
import { DealPipeline, type DealData, type DealStage } from "@/components/ui/deal-pipeline"

const stages: DealStage[] = [
  { id: "qualified", name: "Qualified", probability: 0.1 },
  { id: "proposal", name: "Proposal sent", probability: 0.5 },
  { id: "negotiation", name: "Negotiation", probability: 0.75 },
  { id: "won", name: "Won", probability: 1, kind: "won" },
  { id: "lost", name: "Lost", probability: 0, kind: "lost" },
]

export function B2BSales() {
  const [deals, setDeals] = useState<DealData[]>([
    {
      id: "d01",
      stageId: "proposal",
      title: "CRM licenses, 25 users",
      company: { name: "Tech Solutions Inc." },
      amount: 18000,
      owner: { id: "emma", name: "Emma Carter" },
      expectedCloseDate: "2026-09-30",
    },
    {
      id: "d02",
      stageId: "negotiation",
      title: "ERP integration",
      company: { name: "Construct Group" },
      amount: 103400,
      owner: { id: "liam", name: "Liam Walker" },
      expectedCloseDate: "2026-10-15",
    },
  ])
  return (
    <div className="h-[640px]">
      <DealPipeline
        stages={stages}
        value={deals}
        onValueChange={(next) => setDeals(next)}
        onDealMove={(move) =>
          fetch(`/api/deals/${move.deal.id}`, {
            method: "PATCH",
            body: JSON.stringify({ stageId: move.to.id, lostReason: move.lostReason }),
          }).then((response) => {
            if (!response.ok) throw new Error("Not saved")
          })
        }
        lostReasons={["Price", "Chose a competitor", "Not enough budget", "No decision", "Other reason"]}
        persistKey="pipeline-sales"
        locale="en-US"
        labels={{ lostTitle: "Why did we lose this deal?" }}
      />
    </div>
  )
}

Props

  • stages*
    DealStage[]

    The stages in order: { id, name, probability (0..1, clamped), kind? ("open" | "won" | "lost", default open), tone?, color?, limit? }. Won stages count 100% and are tinted green, lost stages 0% and tinted red; tone / color paint the column dot and the probability bars; limit is the kanban WIP limit.

  • value
    DealData[]

    The deals in order (controlled): { id, stageId, title, company?: { name, logo? }, contact?, amount, currency?, probability? (overrides the stage's), owner?: { id?, name, avatar? }, expectedCloseDate? ("2026-09-30"), stageEnteredAt?, lastActivityAt?, nextStep?, tags?, priority?, lostReason?, href? }. A deal whose stageId does not exist is not shown (a development warning names it).

  • defaultValue
    DealData[]

    The starting deals while uncontrolled. Empty (the default) shows the first-run state.

  • onValueChange
    (deals: DealData[], move?: DealMove) => void

    The whole new array after a drop, a Move to, Mark as won / lost or an added deal. The moved deal carries its new stageId, stageEnteredAt (the moment of the move) and lostReason. move is undefined for added deals and for rollbacks after a failed save.

  • onDealMove
    (move: DealMove) => (void | boolean | Promise<unknown>)

    Runs for every move with { itemId, fromColumnId, toColumnId, fromIndex, toIndex, deal, from, to, lostReason? }. Return false and the card springs back; return a promise and the move is optimistic (the card shows a spinner) and a rejection puts it back and announces it. A drop on a lost stage calls it once the reason is picked.

  • onDealClick
    (deal: DealData) => void

    A click, a tap or Enter on a card or a list row (not after a drag). Without it, a deal with href opens its link.

  • onAddDeal
    (stageId: string, title: string) => (DealData | Promise<DealData> | void)

    Shows + Add deal under every stage. Return the new deal (or a promise of it) and it lands at the end of the stage; a promise shows Add loading and keeps the text if it rejects. Also the action of the empty pipeline's "Add the first deal".

  • getDealActions
    (deal: DealData) => MenuEntry[]

    Your own entries in the card and row ⋯ menu, after Move to, Mark as won and Mark as lost (the dropdown-menu MenuEntry shape; a bottom sheet on phones).

  • renderCard
    (deal: DealData, state: { dragging: boolean; overlay: boolean }) => ReactNode

    Replaces the default DealCard on the board; the board still wraps it in the draggable, focusable surface with the ⋯ menu at its top end. While a card is lifted, deal.stageId is already the stage under it. Build it from DealCardAmount, DealCardProbability, DealCardOwner, DealCardClose and DealCardStale.

  • lostReasons
    string[]

    The lost dialog's reasons, English by default (DEFAULT_LOST_REASONS: Price, Went with a competitor, No budget, No decision, Other). The last one opens a text field for a reason of your own.

  • requireLostReasondefault true
    boolean

    Moving a deal into a lost stage opens the reason dialog first; cancelling it springs the card back. Off, the move commits at once without a reason.

  • view
    "board" | "list"

    The view (controlled); pair it with onViewChange.

  • defaultViewdefault "board"
    "board" | "list"

    The starting view: the kanban board, or a table grouped by stage (cards on phones).

  • onViewChange
    (view: "board" | "list") => void

    Fires when the Board / List switch changes.

  • persistKeydefault ""
    string

    Remembers the view, the owner filter and the closed switch in localStorage under this key (key:view, key:owners, key:closed). Empty remembers nothing.

  • showSummarydefault true
    boolean

    The forecast tiles above the toolbar: open pipeline, weighted forecast, won this month and the win rate.

  • showWeighteddefault true
    boolean

    Weighted totals (amount x probability) in the column headers, the list bands and the summary. Off, the average deal takes the weighted tile's place.

  • showClosed
    boolean

    The won and lost stages (controlled); pair it with onShowClosedChange. Their totals stay in the summary.

  • defaultShowCloseddefault true
    boolean

    Starts with the won and lost stages shown; the toolbar's switch toggles them.

  • onShowClosedChange
    (show: boolean) => void

    Fires when the closed switch changes.

  • ownerFilter
    string[]

    The owners shown (controlled), by owner.id or else the name; empty shows everyone. Pair it with onOwnerFilterChange.

  • defaultOwnerFilter
    string[]

    The starting owner filter while uncontrolled; empty (the default) shows everyone. The summary follows the filter.

  • onOwnerFilterChange
    (owners: string[]) => void

    Fires when an owner chip or All is pressed.

  • staleAfterDaysdefault 14
    number

    Days in an open stage (from stageEnteredAt) before the card gets the amber "18 days in stage" chip; the list shows the days in the same amber badge. 0 never flags.

  • period
    DateRange

    What "won this month" and the win rate count, by the day a deal entered its won / lost stage (else its expected close date). Default: the month of now.

  • columnWidthdefault 288
    number

    Stage width in px on wide boards. Narrow boards show one stage at 85% of the width with the next one peeking.

  • cardVariantdefault "surface"
    "surface" | "outline"

    Cards as raised white (dark: #1A1A1A) panels, or outlined with no fill.

  • sizedefault "md"
    "sm" | "md"

    Density: md has 12px card padding, 14px titles and 17px summary values; sm is 10px, 13px and 15px, with compact list rows.

  • compactAmountsdefault true
    boolean

    Column totals in compact notation ("$56.4K · weighted $5.6K"), and summary values from 1,000,000 ("$1.2M"). Cards and the list always show the full amount.

  • currencydefault "USD"
    string

    ISO 4217 code of the pipeline. Deals in another currency (deal.currency) keep their own on the card and are summed apart with a "+ 2 in EUR" note; nothing is converted.

  • readOnlydefault false
    boolean

    No drag, no + Add deal, no Move to or Mark as won / lost; cards still open and your own actions stay.

  • loadingdefault false
    boolean

    Skeleton tiles in the summary and skeleton cards (or rows) in every stage; the toolbar stays usable.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The open stages' dots and probability bars, the pressed owner chips and the win rate ring. Neutral is black in light mode and white in dark mode; a stage's own tone or color wins.

  • toolbarActions
    ReactNode

    Buttons at the end of the toolbar, like "New deal".

  • now
    Date | number

    The clock for days in stage, overdue dates, the default period and the moment stamped on moved deals. Default useNow(), which is unknown until hydration (those values wait for it).

  • localedefault ""
    string

    Intl locale for amounts, percentages and dates. Empty uses the UIProvider locale, then the browser's.

  • labels
    Partial<DealPipelineLabels>

    Every string, merged over DEFAULT_DEAL_PIPELINE_LABELS: summary, open, weighted, won, winRate, averageDeal, noClosed, summaryLine(open, weighted), winRateHint(won, closed), weightedShort(amount), otherCurrency(count, currency, total), probability(percent), toolbar, view, board, list, owners, allOwners, ownerChip(name, count, formatted), showClosed, closeDate(date), overdue(date), stale(days, formatted), owner(name), saving, markWon, markLost, moveTo, actions(deal), sheetTitle, back, close, listCaption, column headers (columnDeal, columnCompany, columnValue, columnProbability, columnOwner, columnClose, columnDays), dealCount, days, noDeals, lostReason, the lost dialog (lostTitle, lostOther, lostOtherPlaceholder, lostConfirm, cancel), the empty state (emptyTitle, emptyDescription, addFirst), announcements (moved(deal, stage, weighted), wonAnnounce, lostAnnounce, refused, failed, cancelled) and kanban (the board's own KanbanLabels).

  • classNames
    Partial<Record<"summary" | "stat" | "toolbar" | "view" | "owners" | "owner" | "closed" | "actions" | "board" | "nav" | "column" | "columnMeta" | "card" | "list" | "table" | "listCard" | "empty" | "lostDialog", string>>

    Extra classes for the inner parts. Full-bleed phone boards pass board: "-mx-4 px-4 scroll-px-4", nav: "-mx-4 px-4" and owners: "-me-4 pe-4".

  • className
    string

    Extra classes for the root. The board fills the root's height: give the pipeline one (or flex-1 in a column) so stages scroll on their own.

Parts

  • DealCard

    component

    The default card: title, company with its logo, amount with the probability and its 3px bar, the stale chip and tags, the next step, then the owner, priority and close date. Inside a pipeline it reads the stage, locale, currency and clock from it; on its own pass them. Props: { deal: DealData; stage?; size?; variant?; currency?; locale?; now?; staleAfterDays?; tone?; labels?; overlay?; classNames? }.

  • DealCardAmount

    component

    The amount in the deal's currency ("$18,000"), tabular and never wrapping. Props: { deal: DealData; currency?; locale? } & span props.

  • DealCardProbability

    component

    The 3px probability bar (a meter) in the stage's tone; it grows on a gentle spring from where it was when the deal changes stage. Props: { deal: DealData; stage?; tone? } & span props.

  • DealCardOwner

    component

    The owner's 24px avatar and name (showName, default true). Props: { deal: DealData; showName?: boolean } & span props.

  • DealCardClose

    component

    The expected close date ("30 sept.", full: "30.09.2026"); red with a crossed calendar and a spoken "Overdue since" once an open deal is past it. Props: { deal: DealData; full?: boolean; now? } & span props.

  • DealCardStale

    component

    The amber "18 days in stage" badge, only while an open deal is stale. Props: { deal: DealData; staleAfterDays?; now? } & span props.

  • PipelineSummary

    component

    The summary strip alone (a <dl> of tiles), for a dashboard: pass deals and stages, or stats you computed. Narrower than 672px it is a 2 x 2 grid, and narrower than 576px a chevron folds it to one line. Props: { deals?; stages?; stats?; period?; now?; currency?; locale?; tone?; size?; showWeighted?; compactAmounts?; staleAfterDays?; loading?; collapsible?; labels?; classNames? }.

  • computePipelineStats

    function

    The pure math behind the summary and the headers, for servers and dashboards: { byStage: Record<stageId, { count, total, weighted, foreign }>, open, openCount, weighted, won, wonCount, lost, lostCount, winRate, averageDeal, stale, staleIds, foreign, hasWonStage }. Weighted = amount x (deal.probability ?? stage.probability) over open stages; won and lost count within the period; other currencies are summed apart. Signature: (deals: DealData[], stages: DealStage[], options?: { now?; period?; currency?; staleAfterDays? }) => PipelineStats.

  • DEFAULT_DEAL_PIPELINE_LABELS

    constant

    The English strings, to spread under a translation. Type: DealPipelineLabels.

  • DEFAULT_LOST_REASONS

    constant

    The English lost reasons: Price, Went with a competitor, No budget, No decision, Other. Type: string[].

  • DealStage

    type

    One stage: id, name, probability (0 to 1), kind ("open" | "won" | "lost"), tone or color and limit.

  • DealData

    type

    One deal: id, stageId, title, company, contact, amount, currency, probability (overrides the stage's), owner, expectedCloseDate, stageEnteredAt, lastActivityAt, nextStep, tags, priority, lostReason and href.

  • DealPerson

    type

    A deal owner: id, name and avatar.

  • DealMove

    type

    What onDealMove receives: the KanbanMoveEvent fields plus deal, the from and to stages and the lostReason.

  • PipelineStats

    type

    What computePipelineStats returns: byStage, open, openCount, weighted, won, lost, winRate, averageDeal, stale deals and open totals in other currencies.

Examples

List view grouped by stage

A table with a band per stage (count, total, weighted, probability); cards on phones.

One owner, closed hidden

Only Liam Walker's deals and no won / lost columns; the summary follows the filter.

Compact cards through renderCard

A one-line card from DealCardOwner, DealCardAmount and DealCardProbability.

EUR, no lost reason

currency="EUR", requireLostReason={false} and an info tone; a deal in dollars is flagged apart.

Loading, then an empty pipeline

Skeletons in the summary and the columns, then the first-run state that opens the composer.

Phone board

At 375px: the folding summary, scrolling owner chips, stage chips and one column with a peek.

Dependencies

motionlucide-reactavatarbadgebuttondialogdropdown-menuempty-statekanbanprogressradio-groupsegmented-controlskeletonswitchtabletextareatooltipuse-controllable-stateuse-localeuse-persisted-statecommercedate-utilsmotionnumber-formatrelative-timetonesui-config

Files

  • components/ui/deal-pipeline.tsx

FAQ

Is the React Deal Pipeline component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Deal Pipeline?

Run npx wingo-ui@latest add deal-pipeline. It also adds the Wingo UI items it builds on (Avatar, Badge, Button, Dialog, Dropdown Menu and 20 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/deal-pipeline.

How does Deal Pipeline behave on phones?

The summary on top reads the open pipeline, the weighted forecast, what was won this month and the win rate (a small ring); on a phone it is a 2 x 2 grid that folds to one line ("Pipeline $224,850 · weighted $118,065") with a tap on its chevron.

See also

KanbanCRM Pipeline PageStat CardFunnel chartAvatar

Used in

CRM Pipeline Page

More React table and list components

Audit LogEditable GridListMembers tablePermissions MatrixTable
All 11 React table and list components

Articles using this component

  • React CRM Template: Pipeline, Forecast, Company Pages

    Build it: screens and apps · Oct 16, 2026 · 11 min read

  • React Kanban Board: Drag, WIP Limits, Phone Layout

    Component guides · Oct 16, 2026 · 9 min read

  • dnd kit Mobile: Touch Drag That Lets the Page Scroll

    Component guides · Oct 9, 2026 · 11 min read

PreviousData TableNext Editable Grid

B2B sales

Drag a deal to Lost to see the reason dialog

Open pipeline
$224,850
Weighted forecast
$118,065
Won this month
$11,600
Win rate
67%, 2 of 3 closed deals won

Qualified, 3 deals

310% probability10%

$56.4K·weighted $5.6K

  • Client portal

    GRGreen House Realty
    $42,00010%
    Demo with the agents, Sep 29
    Noah HayesCloses 11/20/2026Nov 20
  • Online bookings

    BBistro 21
    $2,40010%
    Mia TurnerCloses 10/30/2026Oct 30
  • License expansion

    TITech Solutions Inc.
    $12,00010%
    Upsell
    Emma CarterCloses 11/15/2026Nov 15

Needs analysis, 2 deals

225% probability25%

$17.1K·weighted $4.3K

  • Billing module

    GPGreenleaf Pharmacy
    $7,20025%
    18 days in stage
    Call Dan Cole about the budget
    Noah HayesCloses 10/10/2026Oct 10
  • Onboarding

    OBOld Mill Bakery
    $9,90025%
    Noah HayesCloses 10/20/2026Oct 20

Proposal sent, 2 deals

250% probability50%

$21.5K·weighted $10.7K

  • CRM licenses, 25 users

    TITech Solutions Inc.
    $18,00050%
    Recurring
    Quote review with Daniel, Sep 26
    Emma CarterHigh priorityCloses 09/30/2026Sep 30
  • Marketing automation

    PSPixel Studio
    $3,45050%
    Mia TurnerOverdue since 09/22/2026Sep 22

Negotiation, 2 deals

275% probability75%

$129.9K·weighted $97.4K

  • ERP integration

    CGConstruct Group
    $103,40075%
    VIP
    The contract is with legal
    Liam WalkerUrgentCloses 10/15/2026Oct 15
  • Data migration

    SLSummit Logistics
    $26,50075%
    Liam WalkerCloses 10/05/2026Oct 5

Won, 2 deals

2

$11.6K

  • Annual plan

    DCDental Art Clinic
    $5,600100%
    Emma CarterCloses 09/15/2026Sep 15
  • CRM licenses, 5 users

    NSNorthwind Studio
    $6,000100%
    Ryan BrooksCloses 09/05/2026Sep 5

Lost, 1 deal

1

$4.8K

  • Extended support

    WBWestside Books
    $4,800
    Not enough budget
    Olivia BennettCloses 09/10/2026Sep 10

lost reason required · persistKey off