Initial push of Plunk Next
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
// Environment configuration
|
||||
// In development: Uses NEXT_PUBLIC_* env vars from .env file
|
||||
// In production (Docker): Build-time values are replaced at container startup via sed
|
||||
|
||||
export const API_URI = process.env.NEXT_PUBLIC_API_URI || 'http://localhost:8080';
|
||||
export const DASHBOARD_URI = process.env.NEXT_PUBLIC_DASHBOARD_URI || 'http://localhost:3000';
|
||||
export const LANDING_URI = process.env.NEXT_PUBLIC_LANDING_URI || 'http://localhost:4000';
|
||||
export const WIKI_URI = process.env.NEXT_PUBLIC_WIKI_URI || 'http://localhost:1000';
|
||||
@@ -0,0 +1,10 @@
|
||||
import {User} from '@prisma/client';
|
||||
import useSWR from 'swr';
|
||||
|
||||
/**
|
||||
* Fetch the current account. undefined means loading, null means logged out
|
||||
*
|
||||
*/
|
||||
export function useAccount() {
|
||||
return useSWR<User | null>('/users/@me', {shouldRetryOnError: false});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import useSWR from 'swr';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function useStats() {
|
||||
return useSWR<{
|
||||
emails: number;
|
||||
events: number;
|
||||
projects: number;
|
||||
contacts: number;
|
||||
}>('/utils', {
|
||||
shouldRetryOnError: false,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import {useEffect, useLayoutEffect, useRef} from 'react';
|
||||
|
||||
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callback
|
||||
* @param delay
|
||||
*/
|
||||
function useInterval(callback: () => void, delay: number | null) {
|
||||
const savedCallback = useRef(callback);
|
||||
|
||||
// Remember the latest callback if it changes.
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
savedCallback.current = callback;
|
||||
}, [callback]);
|
||||
|
||||
// Set up the interval.
|
||||
useEffect(() => {
|
||||
// Don't schedule if no delay is specified.
|
||||
// Note: 0 is a valid value for delay.
|
||||
if (!delay && delay !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = setInterval(() => savedCallback.current(), delay);
|
||||
|
||||
return () => clearInterval(id);
|
||||
}, [delay]);
|
||||
}
|
||||
|
||||
export default useInterval;
|
||||
@@ -0,0 +1,43 @@
|
||||
import {API_URI} from './constants';
|
||||
import {infer as ZodInfer, ZodSchema} from 'zod';
|
||||
|
||||
interface Json {
|
||||
[x: string]: string | number | boolean | Date | Json | JsonArray;
|
||||
}
|
||||
|
||||
type JsonArray = (string | number | boolean | Date | Json | JsonArray)[];
|
||||
|
||||
interface TypedSchema extends ZodSchema {
|
||||
_type: unknown;
|
||||
}
|
||||
|
||||
export class network {
|
||||
/**
|
||||
* Fetcher function that includes toast support
|
||||
* @param method Request method
|
||||
* @param path Request endpoint or path
|
||||
* @param body Request body
|
||||
*/
|
||||
public static async fetch<T, Schema extends TypedSchema | void = void>(
|
||||
method: 'GET' | 'PUT' | 'POST' | 'DELETE',
|
||||
path: string,
|
||||
body?: Schema extends TypedSchema ? ZodInfer<Schema> : never,
|
||||
): Promise<T> {
|
||||
const url = path.startsWith('http') ? path : API_URI + path;
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
body: body && JSON.stringify(body),
|
||||
headers: body && {'Content-Type': 'application/json'},
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
const res = await response.json();
|
||||
|
||||
if (response.status >= 400) {
|
||||
|
||||
throw new Error(res?.message ?? 'Something went wrong!');
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user