Add shared empty states, customer product filters, and SSO handoff across dashboards.

Standardize list empty UI, searchable country fields, customer-products filter row, password/login polish, and one-time business dashboard handoff from the customer app.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-19 19:46:57 +03:30
co-authored by Cursor
parent 832ac32a09
commit f8a9a28346
55 changed files with 1264 additions and 907 deletions
@@ -13,13 +13,9 @@ const PASSWORD_RULES = [
id: 'number',
test: (value: string) => /\d/.test(value),
},
{
id: 'special',
test: (value: string) => /[^A-Za-z0-9]/.test(value),
},
] as const
export type PasswordRuleId = (typeof PASSWORD_RULES)[number]['id']
export type PasswordRuleId = (typeof PASSWORD_RULES)[number]['id'] | 'match'
export type StrengthTone = 'empty' | 'weak' | 'fair' | 'good' | 'strong'
export type PasswordStrengthLabels = {
@@ -43,16 +39,31 @@ const DEFAULT_LABELS: PasswordStrengthLabels = {
length: 'At least 8 characters',
upper: 'One uppercase letter',
number: 'One number',
special: 'One special character',
match: 'Passwords match',
},
}
export function getPasswordChecks(password: string, labels: PasswordStrengthLabels = DEFAULT_LABELS) {
return PASSWORD_RULES.map((rule) => ({
id: rule.id,
label: labels.rules[rule.id],
met: rule.test(password),
}))
function passwordsMatch(password: string, confirmPassword: string) {
return confirmPassword.length > 0 && password === confirmPassword
}
export function getPasswordChecks(
password: string,
labels: PasswordStrengthLabels = DEFAULT_LABELS,
confirmPassword = '',
) {
return [
...PASSWORD_RULES.map((rule) => ({
id: rule.id,
label: labels.rules[rule.id],
met: rule.test(password),
})),
{
id: 'match' as const,
label: labels.rules.match,
met: passwordsMatch(password, confirmPassword),
},
]
}
export function getStrengthMeta(
@@ -88,16 +99,18 @@ export function getPasswordValidationError(
export interface PasswordStrengthMeterProps {
password: string
confirmPassword?: string
labels?: PasswordStrengthLabels
id?: string
}
export function PasswordStrengthMeter({
password,
confirmPassword = '',
labels = DEFAULT_LABELS,
id = 'password-strength',
}: PasswordStrengthMeterProps) {
const checks = getPasswordChecks(password, labels)
const checks = getPasswordChecks(password, labels, confirmPassword)
const metCount = checks.filter((check) => check.met).length
const strength = getStrengthMeta(metCount, password.length > 0, labels)