Typescript conversion.

This commit is contained in:
Mike Cao 2023-11-13 21:36:52 -08:00
parent 366ef35d3d
commit 8775d696b8
29 changed files with 74 additions and 57 deletions

View File

@ -98,7 +98,7 @@
"npm-run-all": "^4.1.5",
"prisma": "5.4.2",
"react": "^18.2.0",
"react-basics": "^0.106.0",
"react-basics": "^0.107.0",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.4",

View File

@ -3,7 +3,7 @@ import { useState } from 'react';
import MobileMenu from './MobileMenu';
import Icons from 'components/icons';
export function HamburgerButton({ menuItems }) {
export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
const [active, setActive] = useState(false);
const handleClick = () => setActive(state => !state);

View File

@ -1,8 +1,8 @@
import { useEffect, useState } from 'react';
import { ReactNode, useEffect, useState } from 'react';
import { Tooltip } from 'react-basics';
import styles from './HoverTooltip.module.css';
export function HoverTooltip({ children }) {
export function HoverTooltip({ children }: { children: ReactNode }) {
const [position, setPosition] = useState({ x: -1000, y: -1000 });
useEffect(() => {

View File

@ -6,7 +6,7 @@ import { ReactNode } from 'react';
export interface LinkButtonProps {
href: string;
className: string;
className?: string;
variant?: string;
scroll?: boolean;
children?: ReactNode;

View File

@ -4,12 +4,19 @@ import { usePathname } from 'next/navigation';
import Link from 'next/link';
import styles from './MobileMenu.module.css';
export function MobileMenu({ items = [], onClose }) {
export function MobileMenu({
items = [],
onClose,
}: {
items: any[];
className?: string;
onClose: () => void;
}) {
const pathname = usePathname();
const Items = ({ items, className }) => (
const Items = ({ items, className }: { items: any[]; className?: string }) => (
<div className={classNames(styles.items, className)}>
{items.map(({ label, url, children }) => {
{items.map(({ label, url, children }: { label: string; url: string; children: any[] }) => {
const selected = pathname.startsWith(url);
return (

View File

@ -3,7 +3,15 @@ import { Button, Icon, Icons } from 'react-basics';
import useMessages from 'components/hooks/useMessages';
import styles from './Pager.module.css';
export function Pager({ page, pageSize, count, onPageChange, className }) {
export interface PagerProps {
page: number;
pageSize: number;
count: number;
onPageChange: (nextPage: number) => void;
className?: string;
}
export function Pager({ page, pageSize, count, onPageChange, className }: PagerProps) {
const { formatMessage, labels } = useMessages();
const maxPage = pageSize && count ? Math.ceil(count / pageSize) : 0;
const lastPage = page === maxPage;
@ -13,7 +21,7 @@ export function Pager({ page, pageSize, count, onPageChange, className }) {
return null;
}
const handlePageChange = value => {
const handlePageChange = (value: number) => {
const nextPage = page + value;
if (nextPage > 0 && nextPage <= maxPage) {
onPageChange(nextPage);

View File

@ -1,2 +1,3 @@
declare module '*.css';
declare module '*.svg';
declare module '*.json';

View File

@ -6,10 +6,10 @@ const countryNames = {
'en-US': enUS,
};
export function useCountryNames(locale) {
export function useCountryNames(locale: string) {
const [list, setList] = useState(countryNames[locale] || enUS);
async function loadData(locale) {
async function loadData(locale: string) {
const { data } = await httpGet(`${process.env.basePath}/intl/country/${locale}.json`);
if (data) {

View File

@ -6,7 +6,7 @@ import websiteStore, { setWebsiteDateRange } from 'store/websites';
import appStore, { setDateRange } from 'store/app';
import useApi from './useApi';
export function useDateRange(websiteId) {
export function useDateRange(websiteId: string) {
const { get } = useApi();
const { locale } = useLocale();
const websiteConfig = websiteStore(state => state[websiteId]?.dateRange);
@ -20,7 +20,7 @@ export function useDateRange(websiteId) {
if (typeof value === 'string') {
if (value === 'all') {
const result = await get(`/websites/${websiteId}/daterange`);
const result: any = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
const startDate = new Date(mindate);

View File

@ -1,6 +1,6 @@
import { useEffect } from 'react';
export function useDocumentClick(handler) {
export function useDocumentClick(handler: (event: MouseEvent) => any) {
useEffect(() => {
document.addEventListener('click', handler);

View File

@ -1,21 +0,0 @@
import { useEffect, useCallback } from 'react';
export function useEscapeKey(handler) {
const escFunction = useCallback(event => {
if (event.keyCode === 27) {
handler(event);
}
}, []);
useEffect(() => {
document.addEventListener('keydown', escFunction, false);
return () => {
document.removeEventListener('keydown', escFunction, false);
};
}, [escFunction]);
return null;
}
export default useEscapeKey;

View File

@ -0,0 +1,21 @@
import { useEffect, useCallback, KeyboardEvent } from 'react';
export function useEscapeKey(handler: (event: KeyboardEvent) => void) {
const escFunction = useCallback((event: KeyboardEvent) => {
if (event.key === 'Escape') {
handler(event);
}
}, []);
useEffect(() => {
document.addEventListener('keydown', escFunction as any, false);
return () => {
document.removeEventListener('keydown', escFunction as any, false);
};
}, [escFunction]);
return null;
}
export default useEscapeKey;

View File

@ -9,23 +9,23 @@ export function useFormat() {
const { locale } = useLocale();
const countryNames = useCountryNames(locale);
const formatBrowser = value => {
const formatBrowser = (value: string) => {
return BROWSERS[value] || value;
};
const formatCountry = value => {
const formatCountry = (value: string) => {
return countryNames[value] || value;
};
const formatRegion = value => {
const formatRegion = (value: string) => {
return regions[value] ? regions[value] : value;
};
const formatDevice = value => {
const formatDevice = (value: string) => {
return formatMessage(labels[value] || labels.unknown);
};
const formatValue = (value, type) => {
const formatValue = (value: string, type: string) => {
switch (type) {
case 'browser':
return formatBrowser(value);

View File

@ -4,13 +4,13 @@ import { messages, labels } from 'components/messages';
export function useMessages() {
const intl = useIntl();
const getMessage = id => {
const getMessage = (id: string) => {
const message = Object.values(messages).find(value => value.id === id);
return message ? formatMessage(message) : id;
};
const formatMessage = (descriptor, values, opts) => {
const formatMessage = (descriptor: any, values?: any, opts?: any) => {
return descriptor ? intl.formatMessage(descriptor, values, opts) : null;
};

View File

@ -18,7 +18,7 @@ export function useReport(reportId, defaultParameters) {
};
const loadReport = async id => {
const data = await get(`/reports/${id}`);
const data: any = await get(`/reports/${id}`);
const { dateRange } = data?.parameters || {};
const { startDate, endDate } = dateRange || {};
@ -40,7 +40,7 @@ export function useReport(reportId, defaultParameters) {
const data = await post(`/reports/${type}`, { ...parameters, timezone });
setReport(
produce(state => {
produce((state: any) => {
state.parameters = parameters;
state.data = data;
@ -56,7 +56,7 @@ export function useReport(reportId, defaultParameters) {
const updateReport = useCallback(
async data => {
setReport(
produce(state => {
produce((state: any) => {
const { parameters, ...rest } = data;
if (parameters) {

View File

@ -1,9 +1,9 @@
import useStore, { setShareToken } from 'store/app';
import useApi from './useApi';
const selector = state => state.shareToken;
const selector = (state: { shareToken: string }) => state.shareToken;
export function useShareToken(shareId) {
export function useShareToken(shareId: string) {
const shareToken = useStore(selector);
const { get, useQuery } = useApi();
const { isLoading, error } = useQuery(['share', shareId], async () => {

View File

@ -5,8 +5,9 @@ export function useSticky({ enabled = true, threshold = 1 }) {
const ref = useRef(null);
useEffect(() => {
let observer;
const handler = ([entry]) => setIsSticky(entry.intersectionRatio < threshold);
let observer: IntersectionObserver | undefined;
const handler: IntersectionObserverCallback = ([entry]) =>
setIsSticky(entry.intersectionRatio < threshold);
if (enabled && ref.current) {
observer = new IntersectionObserver(handler, { threshold: [threshold] });

View File

@ -4,7 +4,7 @@ import { getItem, setItem } from 'next-basics';
import { THEME_COLORS, THEME_CONFIG } from 'lib/constants';
import { colord } from 'colord';
const selector = state => state.theme;
const selector = (state: { theme: string }) => state.theme;
export function useTheme() {
const defaultTheme =

View File

@ -1,6 +1,6 @@
import useApi from './useApi';
export function useWebsite(websiteId) {
export function useWebsite(websiteId: string) {
const { get, useQuery } = useApi();
return useQuery(['websites', websiteId], () => get(`/websites/${websiteId}`), {
enabled: !!websiteId,

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2021",
"outDir": "./build",
"module": "esnext",
"moduleResolution": "node",

View File

@ -7466,10 +7466,10 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-basics@^0.106.0:
version "0.106.0"
resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.106.0.tgz#28ba95a06e6d36adcdb303e1556e6c731b505991"
integrity sha512-CD1qxFu4wrBeNubNo/SkBfWH0BuTErBueNJCCk04IC3qM9poUr3evYfs2S4sfql7dlorcOJ2GflKC1NJ8qPvmw==
react-basics@^0.107.0:
version "0.107.0"
resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.107.0.tgz#e5615792cbb3e4707ba5c8f438b29d6a88cf38b3"
integrity sha512-jYnP1z2LTotxXWYwxOBvF26vXxSUBJB0x62YPKkEr1vmJGeg8iOLr8JGF8KE3R6E+NTqzRt6Bmdtt93mjaog4A==
dependencies:
"@react-spring/web" "^9.7.3"
classnames "^2.3.1"