chore: migrate /icons page to App Router (#18436)

* migrate icons page

* migrate main index page

* remove /icons page

* use i18n string

* fix imports

* add icons_showcase i18n string

* add /app dir to tailwind preset config

* use classname

* do not migrate main index page
This commit is contained in:
Benny Joo
2025-01-02 15:18:19 +05:30
committed by GitHub
parent b1350d0764
commit 85f96f492d
7 changed files with 83 additions and 94 deletions
+1 -3
View File
@@ -16,9 +16,7 @@ async function Error403() {
return (
<div className="bg-subtle flex h-screen">
<div className="rtl: bg-default m-auto rounded-md p-10 text-right ltr:text-left">
<h1 className="font-cal text-emphasis" style={{ fontSize: "3.75rem", lineHeight: 1 }}>
403
</h1>
<h1 className="font-cal text-emphasis text-6xl">403</h1>
<h2 className="text-emphasis mt-6 text-2xl font-medium">{t("dont_have_access_this_page")}</h2>
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">
{t("you_need_admin_or_owner_privileges_to_access")}
+1 -3
View File
@@ -18,9 +18,7 @@ async function Error500({ searchParams }: { searchParams: { error?: string } })
return (
<div className="bg-subtle flex h-screen">
<div className="rtl: bg-default m-auto rounded-md p-10 text-right ltr:text-left">
<h1 className="font-cal text-emphasis" style={{ fontSize: "3.75rem", lineHeight: 1 }}>
500
</h1>
<h1 className="font-cal text-emphasis text-6xl">500</h1>
<h2 className="text-emphasis mt-6 text-2xl font-medium">{t("500_error_message")}</h2>
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">{t("something_went_wrong_on_our_end")}</p>
{searchParams?.error && (
+25
View File
@@ -0,0 +1,25 @@
"use client";
import { Icon } from "@calcom/ui";
import type { IconName } from "@calcom/ui";
export const IconGrid = (props: {
title: string;
icons: IconName[];
rootClassName?: string;
iconClassName?: string;
}) => (
<div className={props.rootClassName}>
<h2 className="font-cal mt-6 text-lg font-medium">{props.title}</h2>
<div className="grid grid-cols-2 lg:grid-cols-6">
{props.icons.map((icon) => {
return (
<div key={icon} className="flex items-center gap-1">
<Icon name={icon} className={props.iconClassName} />
<div>{icon}</div>
</div>
);
})}
</div>
</div>
);
+46
View File
@@ -0,0 +1,46 @@
import { _generateMetadata, getTranslate } from "app/_utils";
import { Inter } from "next/font/google";
import localFont from "next/font/local";
import { type IconName, IconSprites } from "@calcom/ui";
import { lucideIconList } from "../../../../packages/ui/components/icon/icon-list.mjs";
import { IconGrid } from "./IconGrid";
const interFont = Inter({ subsets: ["latin"], variable: "--font-inter", preload: true, display: "swap" });
const calFont = localFont({
src: "../../fonts/CalSans-SemiBold.woff2",
variable: "--font-cal",
preload: true,
display: "swap",
weight: "600",
});
export const generateMetadata = async () => {
return await _generateMetadata(
(t) => t("icon_showcase"),
() => ""
);
};
export default async function IconsPage() {
const icons = Array.from(lucideIconList).sort() as IconName[];
const t = await getTranslate();
return (
<div className={`${interFont.variable} ${calFont.variable}`}>
<div className="bg-subtle flex h-screen">
<IconSprites />
<div className="bg-default m-auto min-w-full rounded-md p-10 text-right ltr:text-left">
<h1 className="text-emphasis font-cal text-2xl font-medium">{t("icons_showcase")}</h1>
<IconGrid title="Regular Icons" icons={icons} />
<IconGrid
title="Filled Icons"
icons={icons}
rootClassName="bg-darkgray-100 text-gray-50"
iconClassName="fill-blue-500"
/>
</div>
</div>
</div>
);
}
export const dynamic = "force-static";
-77
View File
@@ -1,77 +0,0 @@
"use client";
import type { InferGetStaticPropsType } from "next";
import { Inter } from "next/font/google";
import localFont from "next/font/local";
import Head from "next/head";
import { APP_NAME } from "@calcom/lib/constants";
import type { IconName } from "@calcom/ui";
import { Icon, IconSprites } from "@calcom/ui";
import { lucideIconList } from "../../../packages/ui/components/icon/icon-list.mjs";
const interFont = Inter({ subsets: ["latin"], variable: "--font-inter", preload: true, display: "swap" });
const calFont = localFont({
src: "../fonts/CalSans-SemiBold.woff2",
variable: "--font-cal",
preload: true,
display: "swap",
weight: "600",
});
export const getStaticProps = async () => {
return {
props: {
icons: Array.from(lucideIconList).sort() as IconName[],
},
};
};
const IconGrid = (props: {
title: string;
icons: IconName[];
rootClassName?: string;
iconClassName?: string;
}) => (
<div className={props.rootClassName}>
<h2 className="font-cal mt-6 text-lg font-medium">{props.title}</h2>
<div className="grid grid-cols-2 lg:grid-cols-6">
{props.icons.map((icon) => {
return (
<div key={icon} className="flex items-center gap-1">
<Icon name={icon} className={props.iconClassName} />
<div>{icon}</div>
</div>
);
})}
</div>
</div>
);
export default function IconsPage(props: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div className="bg-subtle flex h-screen">
<Head>
<title>Icon showcase | {APP_NAME}</title>
</Head>
<style jsx global>{`
:root {
--font-cal: ${calFont.style.fontFamily};
--font-inter: ${interFont.style.fontFamily};
}
`}</style>
<IconSprites />
<div className="bg-default m-auto min-w-full rounded-md p-10 text-right ltr:text-left">
<h1 className="text-emphasis font-cal text-2xl font-medium">Icons showcase</h1>
<IconGrid title="Regular Icons" icons={props.icons} />
<IconGrid
title="Filled Icons"
icons={props.icons}
rootClassName="bg-darkgray-100 text-gray-50"
iconClassName="fill-blue-500"
/>
</div>
</div>
);
}
+9 -11
View File
@@ -2528,26 +2528,22 @@
"schedule_timezone_change": "Schedule timezone change",
"date": "Date",
"overlaps_with_existing_schedule": "This overlaps with an existing schedule. Please select a different date.",
"org_admin_no_slots|subject": "No availability found for {{name}}",
"org_admin_no_slots|heading": "No availability found for {{name}}",
"org_admin_no_slots|content": "Hello Organization Admins,<br /><br />Please note: It has been brought to our attention that {{username}} has not had any availability when a user has visited {{username}}/{{slug}}<br /><br />There’s a few reasons why this could be happening<br />The user does not have any calendars connected<br />Their schedules attached to this event are not enabled<br /> <br />We recommend checking their availability to resolve this.",
"org_admin_no_slots|cta": "Open users availability",
"organization_no_slots_notification_switch_title": "Get notifications when your team has no availability",
"organization_no_slots_notification_switch_description": "Admins will get email notifications when a user tries to book a team member and is faced with 'No availability'. We trigger this email after two occurrences and remind you every 7 days per user. ",
"email_team_invite|subject|added_to_org": "{{user}} added you to the organization {{team}} on {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} invited you to join the organization {{team}} on {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} added you to the team {{team}} of organization {{parentTeamName}} on {{appName}}",
"email_team_invite|subject|invited_to_subteam": "{{user}} invited you to join the team {{team}} of organization {{parentTeamName}} on {{appName}}",
"email_team_invite|subject|invited_to_regular_team": "{{user}} invited you to join the team {{team}} on {{appName}}",
"email_team_invite|heading|added_to_org": "You’ve been added to a {{appName}} organization",
"email_team_invite|heading|invited_to_org": "You’ve been invited to a {{appName}} organization",
"email_team_invite|heading|added_to_subteam": "You’ve been added to a team of {{parentTeamName}} organization",
"email_team_invite|heading|invited_to_subteam": "You’ve been invited to a team of {{parentTeamName}} organization",
"email_team_invite|heading|invited_to_regular_team": "You’ve been invited to join a {{appName}} team",
"email_team_invite|content|added_to_org": "{{invitedBy}} has added you to the <strong>{{teamName}}</strong> organization.",
"email_team_invite|content|invited_to_org": "{{invitedBy}} has invited you to join the {{teamName}} organization.",
"email_team_invite|content|added_to_subteam": "{{invitedBy}} has added you to the team <strong>{{teamName}}</strong> in their organization {{parentTeamName}}. {{appName}} is the event-juggling scheduler that enables you and your team to schedule meetings without the email tennis.",
@@ -2840,12 +2836,12 @@
"routing_form_insights_booking_status": "Booking Status",
"routing_form_insights_booking_at": "Booking At",
"routing_form_insights_submitted_at": "Submitted At",
"total_bookings_per_period":"Total Bookings per period",
"routed_to_per_period":"Routed to per period",
"total_bookings_per_period": "Total Bookings per period",
"routed_to_per_period": "Routed to per period",
"per_day": "Per day",
"per_week": "Per week",
"per_month": "Per month",
"routing_form_insights_assignment_reason":"Assignment Reason",
"routing_form_insights_assignment_reason": "Assignment Reason",
"access_denied": "Access Denied",
"salesforce_route_to_owner": "Contact owner will be the Round Robin host if available",
"salesforce_do_not_route_to_owner": "Contact owner will not be forced (can still be host if it matches the attributes and Round Robin criteria)",
@@ -2868,7 +2864,7 @@
"rr_distribution_method_availability_description": "Allows bookers to book meetings whenever a host is available. Use this to maximize the number of potential meetings booked and when the even distribution of meetings across hosts is less important.",
"rr_distribution_method_balanced_title": "Load balancing",
"rr_distribution_method_balanced_description": "We will monitor how many bookings have been made with each host and compare this with others, disabling some hosts that are too far ahead so bookings are evenly distributed.",
"require_confirmation_for_free_email": "Only require confirmation for free email providers (Ex. @gmail.com, @outlook.com)",
"require_confirmation_for_free_email": "Only require confirmation for free email providers (Ex. @gmail.com, @outlook.com)",
"exclude_emails_that_contain": "Exclude emails that contain ...",
"require_emails_that_contain": "Require emails that contain ...",
"exclude_emails_match_found_error_message": "Please enter a valid work email address",
@@ -2890,8 +2886,8 @@
"lock_attribute_for_assignment_description": "Locking would only allow assignments from Directory Sync",
"attribute_edited_successfully": "Attribute edited successfully",
"new_group_option": "New group option",
"attribute_weight_enabled":"Weights enabled",
"attribute_weight_enabled_description":"By enabling weights, it would be possible to assign higher priority to certain attributes per user. The higher the weight, the higher the priority.",
"attribute_weight_enabled": "Weights enabled",
"attribute_weight_enabled_description": "By enabling weights, it would be possible to assign higher priority to certain attributes per user. The higher the weight, the higher the priority.",
"routed": "Routed",
"reassigned": "Reassigned",
"rerouted": "Rerouted",
@@ -2906,5 +2902,7 @@
"something_unexpected_occurred": "Something unexpected occurred",
"500_error_message": "It's not you, it's us.",
"dry_run_mode_active": "You are doing a test booking.",
"icon_showcase": "Icon showcase",
"icons_showcase": "Icons showcase",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
}
+1
View File
@@ -6,6 +6,7 @@ const subtleColor = "#E5E7EB";
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./app/**/*.{js,ts,jsx,tsx}",
"./modules/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"../../packages/app-store/**/*{components,pages}/**/*.{js,ts,jsx,tsx}",