Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 9x 9x 293x 250x 250x 245x 43x 39x | import type { RrmProspect } from "../api/admin/rrm";
import { whatsappUrl } from "../crm-constants";
/**
* The by-hand opener (F-21): a `wa.me` link that opens the operator's own
* WhatsApp with the recruitment message pre-filled, for prospects the ladder
* cannot or should not reach (template not approved, campaign halted, a
* number the operator wants to handle personally).
*
* The text is `rrm_partner_opener_v1` word for word, with the same variable
* fallbacks as the ladder (`apps/api/src/lib/rrm/sequence.ts`), plus the
* partner page. Same copy on both paths on purpose — a prospect who later
* gets an automated nudge must read it as the same conversation.
*
* English only: the opener is registered with Meta in `en` and no Telugu
* copy has been approved. Do not translate it here.
*
* No `?p=` visit token: the admin API withholds it as a live credential, so
* a by-hand send is not attributed. The list page's bulk "sent the partner
* link by hand" action is how the stage gets recorded.
*/
/**
* Both hosts come from the build env (`apps/portal/.env.<env>`) so a dev or
* preview portal sends prospects to its own go/partner apps, not production.
* The fallbacks are the production hosts.
*/
export const PARTNER_PAGE_URL: string =
import.meta.env.VITE_PARTNER_PAGE_URL ||
"https://go.interioring.com/partners";
export const PARTNER_APP_URL: string =
import.meta.env.VITE_PARTNER_APP_URL || "https://partners.interioring.com";
type InviteFields = Pick<
RrmProspect,
"phoneNorm" | "name" | "firmName" | "microMarkets"
>;
function firstNameOf(name: string | null): string {
return name?.trim().split(/\s+/)[0] || "there";
}
/** Firm name, else the first micro-market, else "Hyderabad" (ladder design §3). */
function firmOrMicroMarketOf(p: InviteFields): string {
return p.firmName?.trim() || p.microMarkets?.[0]?.trim() || "Hyderabad";
}
export function partnerInviteText(p: InviteFields): string {
return `Hi ${firstNameOf(p.name)}, this is Interioring, Hyderabad. Your buyers ask you about interiors anyway — we get them quotes, review those quotes for them, and pay you ₹100* per validated contact and ₹1,000* when the work goes ahead. Would one of your ${firmOrMicroMarketOf(p)} buyers be worth a quick chat? Reply YES and I'll explain. *Indicative. Reply STOP to opt out.\n\nMore here: ${PARTNER_PAGE_URL}`;
}
/** `https://wa.me/<phone>?text=<opener>` — opens WhatsApp with the message typed, unsent. */
export function partnerInviteUrl(p: InviteFields): string {
return `${whatsappUrl(p.phoneNorm)}?text=${encodeURIComponent(partnerInviteText(p))}`;
}
/**
* The follow-up for someone who has already signed up: where the partner app
* is and how to get in. A follow-up, not an opener, so no boilerplate and no
* STOP line. Sign-in is the WhatsApp number plus a 6-digit code — and the
* code comes from the programme number, not from whichever phone the
* operator sends this from, so the text names that number rather than
* "this chat" (`apps/partner/src/pages/login.tsx`).
*/
export function partnerAppInviteText(p: Pick<InviteFields, "name">): string {
return `Hi ${firstNameOf(p.name)}, your Interioring partner app is at ${PARTNER_APP_URL} — add referrals and track what you have earned there. Sign in with this WhatsApp number; the 6-digit code arrives on WhatsApp from our Interioring number, +91 88972 26999.`;
}
/** Same shape as `partnerInviteUrl`: WhatsApp opened on the prospect's number with the app link typed, unsent. */
export function partnerAppInviteUrl(
p: Pick<InviteFields, "phoneNorm" | "name">,
): string {
return `${whatsappUrl(p.phoneNorm)}?text=${encodeURIComponent(partnerAppInviteText(p))}`;
}
|