Merge from dev to loaf-prod for DEMO #25
@@ -36,6 +36,7 @@
|
||||
"@radix-ui/react-tooltip": "^1.2.4",
|
||||
"@stripe/react-stripe-js": "^2.0.0",
|
||||
"@stripe/stripe-js": "^2.0.0",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"axios": "^1.8.4",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
|
||||
@@ -7,30 +7,77 @@ export const StatCard = ({
|
||||
icon: Icon,
|
||||
iconBgClass,
|
||||
dataTestId,
|
||||
}) => (
|
||||
<Card
|
||||
className="p-6 flex flex-col justify-between bg-background rounded-2xl border border-[var(--neutral-800)]"
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
<div className="flex items-start gap-4 mb-4 ">
|
||||
<div className={`${iconBgClass} p-3 rounded-lg `}>
|
||||
<Icon className="size-8" />
|
||||
</div>
|
||||
}) => {
|
||||
const valueString = value == null ? "" : String(value);
|
||||
|
||||
<div className="space-y-8">
|
||||
<p
|
||||
className="text-6xl font-semibold text-[var(--purple-ink)] mb-1"
|
||||
style={{ fontFamily: "'Inter', sans-serif" }}
|
||||
>
|
||||
{value}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
className="text-sm text-brand-purple "
|
||||
style={{ fontFamily: "'Nunito Sans', sans-serif" }}
|
||||
const digitCount =
|
||||
valueString.replace(/\D/g, "").length || valueString.length;
|
||||
/**
|
||||
*
|
||||
const getValueFontSize = () => {
|
||||
if (digitCount <= 3) {
|
||||
// 3.75rem for 3 or fewer digits
|
||||
return "3.75rem";
|
||||
} else if (digitCount <= 6) {
|
||||
// Scale down for more digits
|
||||
return "clamp(2rem, 5cqi, 3rem)";
|
||||
} else if (digitCount <= 9) {
|
||||
return "clamp(1.5rem, 4cqi, 2.5rem)";
|
||||
} else {
|
||||
return "clamp(1.25rem, 3cqi, 2rem)";
|
||||
}
|
||||
};
|
||||
|
||||
* */
|
||||
|
||||
const getValueFontSize = () => {
|
||||
switch (true) {
|
||||
case digitCount <= 3:
|
||||
// 3.75rem for 3 or fewer digits
|
||||
return "3.75rem";
|
||||
case digitCount <= 6:
|
||||
// Scale down for more digits
|
||||
return "clamp(2rem, 5cqi, 3rem)";
|
||||
case digitCount <= 9:
|
||||
return "clamp(1.5rem, 4cqi, 2.5rem)";
|
||||
default:
|
||||
return "clamp(1.25rem, 3cqi, 2rem)";
|
||||
}
|
||||
};
|
||||
const valueFontSize = getValueFontSize();
|
||||
|
||||
return (
|
||||
<Card
|
||||
className="p-6 flex flex-col justify-between bg-background rounded-2xl border border-[var(--neutral-800)]"
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
{title}
|
||||
</p>
|
||||
</Card>
|
||||
);
|
||||
<div className="flex items-start gap-4 mb-4 justify-between">
|
||||
<div
|
||||
className="space-y-8 "
|
||||
style={{
|
||||
containerType: "inline-size",
|
||||
maxWidth: "200px",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<p
|
||||
className="font-semibold text-[var(--purple-ink)] mb-1"
|
||||
style={{ fontSize: valueFontSize, lineHeight: 1 }}
|
||||
>
|
||||
{value}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={`${iconBgClass} p-3 rounded-lg `}>
|
||||
<Icon className="size-8" />
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
className="text-sm text-brand-purple "
|
||||
style={{ fontFamily: "'Nunito Sans', sans-serif" }}
|
||||
>
|
||||
{title}
|
||||
</p>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -60,7 +60,7 @@ const AdminDashboard = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex justify-between items-center'>
|
||||
<div className='flex flex-col md:flex-row md:justify-between md:items-center'>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl md:text-5xl font-semibold text-[var(--purple-ink)] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Admin Dashboard
|
||||
@@ -69,9 +69,9 @@ const AdminDashboard = () => {
|
||||
Manage users, events, and membership applications.
|
||||
</p>
|
||||
</div>
|
||||
<Link to={'/'}>
|
||||
<Link to={'/'} className=''>
|
||||
<Button
|
||||
className="btn-lavender"
|
||||
className="btn-lavender mb-8 md:mb-0 "
|
||||
>
|
||||
<Globe />
|
||||
View Public Site
|
||||
|
||||
@@ -244,7 +244,7 @@ const AdminMembers = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-8">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start mb-4">
|
||||
<div>
|
||||
<h1 className="text-4xl md:text-5xl font-semibold text-[var(--purple-ink)] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Members Management
|
||||
@@ -253,7 +253,7 @@ const AdminMembers = () => {
|
||||
Manage paying members and their subscriptions.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
<div className="flex gap-3 flex-wrap ">
|
||||
{hasPermission('users.export') && (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
|
||||
@@ -132,7 +132,7 @@ const AdminStaff = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-8">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start mb-4">
|
||||
<div>
|
||||
<h1 className="text-4xl md:text-5xl font-semibold text-[var(--purple-ink)] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Staff Management
|
||||
@@ -141,7 +141,7 @@ const AdminStaff = () => {
|
||||
Manage internal team members and their roles.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<div className="flex gap-3 ">
|
||||
{hasPermission('users.create') && (
|
||||
<Button
|
||||
onClick={() => setInviteDialogOpen(true)}
|
||||
@@ -194,13 +194,13 @@ const AdminStaff = () => {
|
||||
|
||||
{/* Tabs */}
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="mb-8">
|
||||
<TabsList className="grid w-full grid-cols-2 mb-8">
|
||||
<TabsTrigger value="staff-list" className="text-lg py-3">
|
||||
<UserCog className="h-5 w-5 mr-2" />
|
||||
<TabsList className="grid w-full grid-cols-2 mb-8 ">
|
||||
<TabsTrigger value="staff-list" className="text-sm sm:text-md md:text-lg py-3">
|
||||
<UserCog className="h-5 w-5 mr-2 hidden md:inline" />
|
||||
Staff Members
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="pending-invitations" className="text-lg py-3 ">
|
||||
<Mail className="h-5 w-5 mr-2" />
|
||||
<TabsTrigger value="pending-invitations" className="text-sm sm:text-md md:text-lg py-3 ">
|
||||
<Mail className="h-5 w-5 mr-2 hidden md:inline" />
|
||||
Pending Invitations
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
@@ -54,3 +54,4 @@ h6 {
|
||||
#ffffff 100%
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ module.exports = {
|
||||
|
||||
plugins: [
|
||||
require("tailwindcss-animate"),
|
||||
require("@tailwindcss/typography")
|
||||
require("@tailwindcss/typography"),
|
||||
require('@tailwindcss/line-clamp')
|
||||
],
|
||||
};
|
||||
@@ -2552,6 +2552,11 @@
|
||||
"@svgr/plugin-svgo" "^5.5.0"
|
||||
loader-utils "^2.0.0"
|
||||
|
||||
"@tailwindcss/line-clamp@^0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz#767cf8e5d528a5d90c9740ca66eb079f5e87d423"
|
||||
integrity sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==
|
||||
|
||||
"@tailwindcss/typography@^0.5.19":
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.19.tgz#ecb734af2569681eb40932f09f60c2848b909456"
|
||||
|
||||
Reference in New Issue
Block a user