mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-29 10:16:32 +02:00
Fixed remaning linting issues
This commit is contained in:
parent
a13df41bae
commit
b7765013ca
33 changed files with 140 additions and 1495 deletions
|
@ -78,7 +78,10 @@ export const TimesShownIn = () => {
|
|||
|
||||
return (
|
||||
<ClockPreferences>
|
||||
<button className="inline-flex items-center gap-x-2.5 text-sm hover:underline">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-x-2.5 text-sm hover:underline"
|
||||
>
|
||||
<GlobeIcon className="size-4" />
|
||||
<Trans
|
||||
i18nKey="timeShownIn"
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
import { DateLocalizer } from "react-big-calendar";
|
||||
|
||||
const weekRangeFormat = ({ start, end }, culture, local) =>
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
local.format(start, "MMMM DD", culture) +
|
||||
" – " +
|
||||
" - " +
|
||||
local.format(end, local.eq(start, end, "month") ? "DD" : "MMMM DD", culture);
|
||||
|
||||
const dateRangeFormat = ({ start, end }, culture, local) =>
|
||||
local.format(start, "L", culture) + " – " + local.format(end, "L", culture);
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
local.format(start, "L", culture) + " - " + local.format(end, "L", culture);
|
||||
|
||||
const timeRangeFormat = ({ start, end }, culture, local) =>
|
||||
local.format(start, "LT", culture) + " – " + local.format(end, "LT", culture);
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
local.format(start, "LT", culture) + " - " + local.format(end, "LT", culture);
|
||||
|
||||
const timeRangeStartFormat = ({ start }, culture, local) =>
|
||||
local.format(start, "LT", culture) + " – ";
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
local.format(start, "LT", culture) + " - ";
|
||||
|
||||
const timeRangeEndFormat = ({ end }, culture, local) =>
|
||||
" – " + local.format(end, "LT", culture);
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
" - " + local.format(end, "LT", culture);
|
||||
|
||||
export const formats = {
|
||||
dateFormat: "DD",
|
||||
|
@ -62,6 +66,7 @@ export default function (dayjs) {
|
|||
return [dtA, dtB, datePart];
|
||||
}
|
||||
|
||||
// biome-ignore lint/style/useDefaultParameterLast: <explanation>
|
||||
function startOf(date = null, unit) {
|
||||
const datePart = fixUnit(unit);
|
||||
if (datePart) {
|
||||
|
@ -70,6 +75,7 @@ export default function (dayjs) {
|
|||
return dayjs(date).toDate();
|
||||
}
|
||||
|
||||
// biome-ignore lint/style/useDefaultParameterLast: <explanation>
|
||||
function endOf(date = null, unit) {
|
||||
const datePart = fixUnit(unit);
|
||||
if (datePart) {
|
||||
|
|
|
@ -70,7 +70,7 @@ const PollOptionsForm = ({
|
|||
[views, watchView],
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||
const watchOptions = watch("options", [])!;
|
||||
const watchDuration = watch("duration");
|
||||
const watchTimeZone = watch("timeZone");
|
||||
|
|
|
@ -51,14 +51,14 @@ const SettingTitle = ({
|
|||
|
||||
const Setting = ({ children }: React.PropsWithChildren) => {
|
||||
return (
|
||||
<label
|
||||
<div
|
||||
className={cn(
|
||||
"cursor-pointer bg-white hover:bg-gray-50 active:bg-gray-100",
|
||||
"flex select-none justify-between gap-x-4 gap-y-2.5 rounded-md border p-3 sm:flex-row ",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ export type NewEventData = PollDetailsData &
|
|||
PollOptionsData &
|
||||
PollSettingsFormData;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
export interface PollFormProps<T extends Record<string, any>> {
|
||||
onSubmit?: (data: T) => void;
|
||||
onChange?: (data: Partial<T>) => void;
|
||||
|
|
|
@ -80,9 +80,9 @@ export const InviteDialog = () => {
|
|||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="min-w-0">
|
||||
<label className="mb-2">
|
||||
<div className="mb-2">
|
||||
<Trans i18nKey="inviteLink" defaults="Invite Link" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<CopyInviteLinkButton />
|
||||
<div className="shrink-0">
|
||||
|
|
|
@ -77,7 +77,7 @@ const ModalProvider: React.FunctionComponent<ModalProviderProps> = ({
|
|||
))}
|
||||
{modals.map((props, i) => (
|
||||
<Modal
|
||||
key={i}
|
||||
key={`modal-${i}-${props.title}`}
|
||||
visible={true}
|
||||
{...props}
|
||||
content={
|
||||
|
|
|
@ -161,7 +161,7 @@ export const NewParticipantForm = (props: NewParticipantModalProps) => {
|
|||
) : null}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label className="mb-1 text-gray-500">{t("response")}</label>
|
||||
<div className="mb-1 text-sm text-gray-500">{t("response")}</div>
|
||||
<VoteSummary votes={props.votes} />
|
||||
</fieldset>
|
||||
{formState.errors.root?.message ? (
|
||||
|
|
|
@ -303,7 +303,7 @@ const DesktopPoll: React.FunctionComponent = () => {
|
|||
? visibleParticipants.map((participant, i) => {
|
||||
return (
|
||||
<ParticipantRow
|
||||
key={i}
|
||||
key={participant.id}
|
||||
participant={{
|
||||
id: participant.id,
|
||||
name: participant.name,
|
||||
|
|
|
@ -19,7 +19,7 @@ import { YouAvatar } from "@/components/poll/you-avatar";
|
|||
import { Trans } from "@/components/trans";
|
||||
|
||||
import { usePoll } from "../../poll-context";
|
||||
import { toggleVote, VoteSelector } from "../vote-selector";
|
||||
import { VoteSelector, toggleVote } from "../vote-selector";
|
||||
|
||||
export interface ParticipantRowFormProps {
|
||||
name?: string;
|
||||
|
@ -112,24 +112,32 @@ const ParticipantRowForm = ({
|
|||
<Controller
|
||||
control={form.control}
|
||||
name={`votes.${i}`}
|
||||
render={({ field }) => (
|
||||
<div
|
||||
onClick={() => {
|
||||
field.onChange({
|
||||
optionId,
|
||||
type: toggleVote(field.value?.type),
|
||||
});
|
||||
}}
|
||||
className="absolute inset-0 flex cursor-pointer items-center justify-center hover:bg-gray-100 active:bg-gray-200/50 active:ring-1 active:ring-inset active:ring-gray-200"
|
||||
>
|
||||
<VoteSelector
|
||||
value={field.value?.type}
|
||||
onChange={(vote) => {
|
||||
field.onChange({ optionId, type: vote });
|
||||
render={({ field }) => {
|
||||
const handleChange = () => {
|
||||
field.onChange({
|
||||
optionId,
|
||||
type: toggleVote(field.value?.type),
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div
|
||||
onClick={handleChange}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
handleChange();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
className="absolute inset-0 flex cursor-pointer items-center justify-center hover:bg-gray-100 active:bg-gray-200/50 active:ring-1 active:ring-inset active:ring-gray-200"
|
||||
>
|
||||
<VoteSelector
|
||||
value={field.value?.type}
|
||||
onChange={(vote) => {
|
||||
field.onChange({ optionId, type: vote });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
);
|
||||
|
|
|
@ -68,7 +68,7 @@ export const ParticipantRowView: React.FunctionComponent<{
|
|||
{votes.map((vote, i) => {
|
||||
return (
|
||||
<td
|
||||
key={i}
|
||||
key={`vote-${i}-${vote}`}
|
||||
className={cn(
|
||||
"h-12 border-l border-t",
|
||||
!vote || vote === "no" ? "bg-gray-100" : "bg-white",
|
||||
|
@ -109,7 +109,7 @@ const ParticipantRow: React.FunctionComponent<ParticipantRowProps> = ({
|
|||
const { user, ownsObject } = useUser();
|
||||
const { getVote, optionIds } = usePoll();
|
||||
|
||||
const isYou = !!(user && ownsObject(participant) );
|
||||
const isYou = !!(user && ownsObject(participant));
|
||||
|
||||
const { canEditParticipant } = usePermissions();
|
||||
const canEdit = canEditParticipant(participant.id);
|
||||
|
|
|
@ -51,19 +51,19 @@ const useScoreByOptionId = () => {
|
|||
|
||||
return React.useMemo(() => {
|
||||
const scoreByOptionId: Record<string, OptionScore> = {};
|
||||
options.forEach((option) => {
|
||||
for (const option of options) {
|
||||
scoreByOptionId[option.id] = {
|
||||
yes: [],
|
||||
ifNeedBe: [],
|
||||
no: [],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
responses?.forEach((response) => {
|
||||
response.votes.forEach((vote) => {
|
||||
for (const response of responses) {
|
||||
for (const vote of response.votes) {
|
||||
scoreByOptionId[vote.optionId]?.[vote.type].push(response.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return scoreByOptionId;
|
||||
}, [responses, options]);
|
||||
|
|
|
@ -48,8 +48,8 @@ const PollOptionVoteSummary: React.FunctionComponent<{ optionId: string }> = ({
|
|||
) : (
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="col-span-1 space-y-2.5">
|
||||
{participantsWhoVotedYes.map(({ name }, i) => (
|
||||
<div key={i} className="flex">
|
||||
{participantsWhoVotedYes.map(({ id, name }) => (
|
||||
<div key={id} className="flex">
|
||||
<div className="relative mr-2.5 flex size-5 items-center justify-center">
|
||||
<OptimizedAvatarImage size="xs" name={name} />
|
||||
<VoteIcon
|
||||
|
@ -61,8 +61,8 @@ const PollOptionVoteSummary: React.FunctionComponent<{ optionId: string }> = ({
|
|||
<div className="truncate text-sm">{name}</div>
|
||||
</div>
|
||||
))}
|
||||
{participantsWhoVotedIfNeedBe.map(({ name }, i) => (
|
||||
<div key={i} className="flex">
|
||||
{participantsWhoVotedIfNeedBe.map(({ id, name }) => (
|
||||
<div key={id} className="flex">
|
||||
<div className="relative mr-2.5 flex size-5 items-center justify-center">
|
||||
<OptimizedAvatarImage size="xs" name={name} />
|
||||
<VoteIcon
|
||||
|
@ -76,8 +76,8 @@ const PollOptionVoteSummary: React.FunctionComponent<{ optionId: string }> = ({
|
|||
))}
|
||||
</div>
|
||||
<div className="col-span-1 space-y-2.5">
|
||||
{participantsWhoVotedNo.map(({ name }, i) => (
|
||||
<div key={i} className="flex">
|
||||
{participantsWhoVotedNo.map(({ id, name }) => (
|
||||
<div key={id} className="flex">
|
||||
<div className="relative mr-2.5 flex size-5 items-center justify-center">
|
||||
<OptimizedAvatarImage size="xs" name={name} />
|
||||
<VoteIcon
|
||||
|
@ -122,6 +122,17 @@ const PollOption: React.FunctionComponent<PollOptionProps> = ({
|
|||
onClick={() => {
|
||||
selectorRef.current?.click();
|
||||
}}
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
selectorRef.current?.click();
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === " ") {
|
||||
e.preventDefault();
|
||||
selectorRef.current?.click();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex h-7 items-center justify-between gap-x-4">
|
||||
<div className="shrink-0">{children}</div>
|
||||
|
|
|
@ -72,6 +72,14 @@ export function ScheduledEvent() {
|
|||
|
||||
const attendees = useAttendees();
|
||||
|
||||
const guestEmails: string[] = [];
|
||||
|
||||
for (const attendee of attendees) {
|
||||
if (attendee.email) {
|
||||
guestEmails.push(attendee.email);
|
||||
}
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
return null;
|
||||
}
|
||||
|
@ -116,9 +124,7 @@ export function ScheduledEvent() {
|
|||
? { name: poll.user.name, email: poll.user.email }
|
||||
: undefined
|
||||
}
|
||||
guests={attendees
|
||||
.filter((participant) => !!participant.email)
|
||||
.map((participant) => participant.email!)}
|
||||
guests={guestEmails}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -106,7 +106,10 @@ const DateTimePreferencesForm = () => {
|
|||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{dayjs.weekdays().map((day, index) => (
|
||||
<SelectItem key={index} value={index.toString()}>
|
||||
<SelectItem
|
||||
key={index.toString()}
|
||||
value={index.toString()}
|
||||
>
|
||||
{day}
|
||||
</SelectItem>
|
||||
))}
|
||||
|
|
|
@ -27,7 +27,7 @@ const Steps: React.FunctionComponent<StepsProps> = ({
|
|||
{[...Array(total)].map((_, i) => {
|
||||
return (
|
||||
<span
|
||||
key={i}
|
||||
key={i.toString()}
|
||||
className={cn("h-2 w-2 rounded-full transition-all", {
|
||||
"bg-primary-400": i <= current,
|
||||
"bg-gray-300": i > current,
|
||||
|
|
|
@ -20,6 +20,7 @@ export function DataTableColumnHeader<TData, TValue>({
|
|||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full items-center gap-x-2.5"
|
||||
onClick={() => {
|
||||
column.toggleSorting();
|
||||
|
|
|
@ -17,18 +17,18 @@ const TimeFormatPicker = ({
|
|||
return (
|
||||
<RadioGroup value={value} onValueChange={onChange} disabled={disabled}>
|
||||
<div className="grid gap-y-1">
|
||||
<label className="flex items-center gap-x-2">
|
||||
<RadioGroupItem value="hours12" />
|
||||
<span>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<RadioGroupItem id="hours12" value="hours12" />
|
||||
<label htmlFor="hours12">
|
||||
<Trans i18nKey="12h" />
|
||||
</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-x-2">
|
||||
<RadioGroupItem value="hours24" />
|
||||
<span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<RadioGroupItem id="hours24" value="hours24" />
|
||||
<label htmlFor="hours24">
|
||||
<Trans i18nKey="24h" />
|
||||
</span>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Button } from "@rallly/ui/button";
|
||||
import Link from "next/link";
|
||||
import { Trans } from "next-i18next";
|
||||
import Link from "next/link";
|
||||
import type React from "react";
|
||||
|
||||
import { usePostHog } from "@/utils/posthog";
|
||||
|
@ -39,7 +39,7 @@ export const UpgradeButton = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const UpgradeLink = ({}) => {
|
||||
export const UpgradeLink = () => {
|
||||
return (
|
||||
<Button variant="primary" asChild>
|
||||
<Link href="/settings/billing">
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function GlobalError({
|
|||
}, [error]);
|
||||
|
||||
return (
|
||||
<html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
{/* `NextError` is the default Next.js error page component. Its type
|
||||
definition requires a `statusCode` prop. However, since the App Router
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import crypto from "node:crypto";
|
||||
// Original source: https://gist.github.com/dsumer/3594cda57e84a93a9019cddc71831882
|
||||
import { prisma } from "@rallly/database";
|
||||
import crypto from "node:crypto";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import * as Serialize from "php-serialize";
|
||||
|
||||
|
@ -55,7 +55,7 @@ export function validateWebhook(req: NextApiRequest) {
|
|||
jsonObj = ksort(jsonObj);
|
||||
for (const property in jsonObj) {
|
||||
if (
|
||||
jsonObj.hasOwnProperty(property) &&
|
||||
Object.hasOwn(jsonObj, property) &&
|
||||
typeof jsonObj[property] !== "string"
|
||||
) {
|
||||
if (Array.isArray(jsonObj[property])) {
|
||||
|
|
|
@ -18,7 +18,7 @@ function joinPath(baseUrl: string, subpath = "") {
|
|||
export function objectToQueryString(obj: Record<string, string>) {
|
||||
const parts = [];
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (Object.hasOwn(obj, key)) {
|
||||
const value = obj[key];
|
||||
if (value !== undefined) {
|
||||
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import dayjs from "dayjs";
|
||||
|
||||
import { supportedTimeZones } from "@/utils/supported-time-zones";
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import type {
|
||||
DateTimeOption,
|
||||
|
@ -67,11 +67,20 @@ export function normalizeTimeZone(timeZone: string) {
|
|||
return dayjs().tz(tz, true).utcOffset() === timeZoneOffset;
|
||||
});
|
||||
}
|
||||
|
||||
if (!tz) {
|
||||
tz = supportedTimeZones.find((tz) => {
|
||||
return getTimeZoneOffset(tz) === timeZoneOffset;
|
||||
})!; // We assume there has to be a timezone with the same offset
|
||||
});
|
||||
|
||||
if (!tz) {
|
||||
Sentry.captureException(
|
||||
new Error(`Failed to resolve timezone ${timeZone}`),
|
||||
);
|
||||
// TODO: This shouldn't happen since there is at least one timezone with the same offset
|
||||
// that is supported by the application, but at least we have a fallback.
|
||||
// We should prompt the user for their timezone if we can't resolve it automatically.
|
||||
tz = "Europe/London";
|
||||
}
|
||||
}
|
||||
|
||||
return tz;
|
||||
|
|
|
@ -225,7 +225,7 @@ export const DayjsProvider: React.FunctionComponent<{
|
|||
if (!localTime) {
|
||||
return dayjs(date).tz(preferredTimeZone);
|
||||
}
|
||||
return dayjs(date).utc();
|
||||
return dayjs(date).utc();
|
||||
},
|
||||
[preferredTimeZone],
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ export function getValueByPath<O extends Record<string, unknown>>(
|
|||
path: string,
|
||||
): unknown {
|
||||
const pathArray = path.split(".");
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
let curr: any = obj;
|
||||
for (const part of pathArray) {
|
||||
if (curr[part] === undefined) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"useIgnoreFile": false
|
||||
},
|
||||
"linter": {
|
||||
"ignore": ["node_modules", ".next", "dist"],
|
||||
"ignore": ["node_modules", ".next", "dist", "public/static/scripts"],
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@rallly/ui": "workspace:*",
|
||||
"@rallly/database": "workspace:*",
|
||||
"stripe": "^13.2.0",
|
||||
"@radix-ui/react-radio-group": "^1.2.0",
|
||||
"next": "*"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { prisma } from "@rallly/database";
|
||||
/**
|
||||
* This script will go through all subscriptions and add the userId to the metadata.
|
||||
*/
|
||||
import { stripe } from "../lib/stripe";
|
||||
import { prisma } from "@rallly/database";
|
||||
|
||||
async function getSubscriptionsWithMissingMetadata(
|
||||
starting_after?: string,
|
||||
|
@ -13,11 +13,11 @@ async function getSubscriptionsWithMissingMetadata(
|
|||
limit: 100,
|
||||
starting_after,
|
||||
});
|
||||
subscriptions.data.forEach((subscription) => {
|
||||
for (const subscription of subscriptions.data) {
|
||||
if (!subscription.metadata.userId) {
|
||||
res.push(subscription.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (subscriptions.has_more) {
|
||||
return [
|
||||
...res,
|
||||
|
@ -26,7 +26,7 @@ async function getSubscriptionsWithMissingMetadata(
|
|||
)),
|
||||
];
|
||||
}
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
async function normalizeSubscriptionMetadata() {
|
||||
|
|
|
@ -20,6 +20,7 @@ const prismaClientSingleton = () => {
|
|||
|
||||
export type ExtendedPrismaClient = ReturnType<typeof prismaClientSingleton>;
|
||||
|
||||
// biome-ignore lint/suspicious/noShadowRestrictedNames: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/nextjs-prisma-client-dev-practices
|
||||
declare const globalThis: {
|
||||
prismaGlobal: ExtendedPrismaClient;
|
||||
} & typeof global;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"@rallly/tsconfig": "workspace:*",
|
||||
"@types/node": "^18.15.10",
|
||||
"prisma": "^5.17.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"tsx": "^4.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -160,9 +160,9 @@ async function main() {
|
|||
|
||||
await Promise.all(
|
||||
[freeUser, proUser, proUserLegacy].map(async (user) => {
|
||||
Array.from({ length: 20 }).forEach(async () => {
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await createPollForUser(user.id);
|
||||
});
|
||||
}
|
||||
console.info(`✓ Added ${user.email}`);
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type React from "react";
|
||||
|
||||
type ComponentPropsAs<
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
C extends React.ElementType<any>,
|
||||
T extends React.ComponentPropsWithoutRef<C>["as"],
|
||||
> = Omit<
|
||||
|
|
1420
pnpm-lock.yaml
generated
1420
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue