Skip to content

Commit

Permalink
Convert to TypeScript (#15)
Browse files Browse the repository at this point in the history
* Upgraded NextAuth.js & Prisma

* Upgraded TailwindCSS to v3

* Removed TailwindCSS `mode` as `jit` is now default

* Minor TailwindCSS config migration tweaks

* Purged `transform` class usage

* Added currentColor to TailwindCSS theme colors

https://tailwindcss.com/docs/upgrade-guide#fill-and-stroke-use-color-palette

* Added TypeScript to dev dependencies

* Added initial TypeScript config

* Added next-env.d.ts

* Initial TypeScript migration

* Upgraded all neccessary packages + moved Prettier to dev dependency

* Updated package-lock.json

* Updated packae-lock.json

* Added shared fetcher

* Initial components TypeScript overhaul

* Added @types/js-cookie

* Added @types import path alias

* Deleted jsconfig.json

* Added initial Cloudinary TypeScript support

* Fixed app layout optional prop

* Added method validation to all "save" endpoints

* Updated package-lock.json

* Removed console.log

* Minor cloudinary type fixes

* Fixed cloudinary mouse event type

* Console.log tweaks

* Fixed NextAuth.js session user id/username

* Migrated app index/login page to TypeScript

* Added initial sites [slug] page TypeScript migration

* Added initial sites index page migration to TypeScript

* Migrated domain card component to TypeScript

* Cleaned up app settings page user session type

* Improved API endpoints error handling

* Added reusable UserSettings type

* Removed array-to-image dependency

* Upgraded save-image function to TypeScript

* Added custom NextAuth type declarations

Overrides default Session & User interfaces to add additional id & username properties

* Improved middleware error handling

* Fixed image placeholder

* Minor TODO fixes

* Minor type tweaks / fixes

* Fixed multiple types / TODO's

* Updated API endpoints to new structure following #25

* Moved method logic handling to lib directory

vercel/platforms#25 (comment)

* Added HttpMethod enum

* Cleaned up API domain structure

* Removed old domain endpoints

* refactor: refactor app/post to typescript

Refactor the postId & settings pages to use tsx

* refactor: address PR comments

* Minor cleanup

* Minor cleanup

* Migrated site/[id] pages to TypeScript

* Updated HTTP methods to use enum

* Fixed nested anchor element errors using passHref

* Fixed login page svg error

* Migrated remark plugins to TypeScript

* Added initial Twitter types

* Migrated Twitter media to TypeScript

* Migrated Twitter lib function(s) to TypeScript

* Migrated sites layout component to TypeScript

* Migrate Tweet.js to Typescript

* Updated OAuth env vars check to use GitHub

* Code review fixes

* Minor tweaks / fixes

* Fixed format:write script

* Minor cleanup

* Fix security issue (#54)

* Removed old post/site JS api endpoints

* Fixed image upload bug

* Added @type & disabled swcMinify in Next.js config

* minor fixes

* Fixes from main branch merge

* Cleaned up revalidate function

* update to latest API

* removed some .js files

* Cleaned up middleware

* bug: Remove leaked Post type from prisma client

* Added error toast to post index page

* Refactored getStatic props to export types

* Fixed Prisma client leak bug

* fixed a few small changes

* fixed some type issues

* Update _middleware.ts

Co-authored-by: Cillian Barron <[email protected]>
Co-authored-by: Francisco Hanna <[email protected]>
Co-authored-by: Steven Tey <[email protected]>
  • Loading branch information
4 people authored Mar 18, 2022
1 parent a1dd8e6 commit 327dfa1
Show file tree
Hide file tree
Showing 92 changed files with 2,997 additions and 1,416 deletions.
33 changes: 0 additions & 33 deletions components/BlogCard.js

This file was deleted.

48 changes: 48 additions & 0 deletions components/BlogCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Link from "next/link";
import BlurImage from "./BlurImage";
import Date from "./Date";

import type { Post } from "@prisma/client";

interface BlogCardProps {
data: Pick<
Post,
"slug" | "image" | "imageBlurhash" | "title" | "description" | "createdAt"
>;
}

export default function BlogCard({ data }: BlogCardProps) {
return (
<Link href={`/${data.slug}`}>
<a>
<div className="rounded-2xl border-2 border-gray-100 overflow-hidden shadow-md bg-white hover:shadow-xl hover:-translate-y-1 transition-all ease duration-200">
{data.image ? (
<BlurImage
src={data.image}
alt={data.title ?? "Blog "}
width={500}
height={400}
layout="responsive"
objectFit="cover"
placeholder="blur"
blurDataURL={data.imageBlurhash ?? undefined}
/>
) : (
<div className="absolute flex items-center justify-center w-full h-full bg-gray-100 text-gray-500 text-4xl select-none">
?
</div>
)}
<div className="py-8 px-5 h-36 border-t border-gray-200">
<h3 className="font-cal text-xl tracking-wide">{data.title}</h3>
<p className="text-md italic text-gray-600 my-2 truncate">
{data.description}
</p>
<p className="text-sm text-gray-600 my-2">
Published <Date dateString={data.createdAt.toString()} />
</p>
</div>
</div>
</a>
</Link>
);
}
11 changes: 9 additions & 2 deletions components/BlurImage.js → components/BlurImage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import cn from "clsx";
import Image from "next/image";
import { useState } from "react";
import cn from "clsx";

export default function BlurImage(props) {
import type { ComponentProps } from "react";
import type { WithClassName } from "@/types";

interface BlurImageProps extends WithClassName, ComponentProps<typeof Image> {
alt: string;
}

export default function BlurImage(props: BlurImageProps) {
const [isLoading, setLoading] = useState(true);

return (
Expand Down
48 changes: 0 additions & 48 deletions components/Cloudinary.js

This file was deleted.

59 changes: 59 additions & 0 deletions components/Cloudinary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Head from "next/head";

import type { MouseEvent, ReactNode } from "react";
import type {
CloudinaryCallbackImage,
CloudinaryWidget,
CloudinaryWidgetResult,
} from "@/types";

interface ChildrenProps {
open: (e: MouseEvent) => void;
}

interface CloudinaryUploadWidgetProps {
callback: (image: CloudinaryCallbackImage) => void;
children: (props: ChildrenProps) => ReactNode;
}

export default function CloudinaryUploadWidget({
callback,
children,
}: CloudinaryUploadWidgetProps) {
function showWidget() {
const widget: CloudinaryWidget = window.cloudinary.createUploadWidget(
{
cloudName: "vercel-platforms",
uploadPreset: "w0vnflc6",
cropping: true,
},
(error: unknown | undefined, result: CloudinaryWidgetResult) => {
if (!error && result && result.event === "success") {
callback(result.info);
}
}
);

widget.open();
}

function open(e: MouseEvent) {
e.preventDefault();
showWidget();
}

return (
<>
<Head>
// this is Next.js specific, but if you're using something like Create
React App, // you could download the script in componentDidMount using
this method: https://stackoverflow.com/a/34425083/1424568
<script
src="https://widget.cloudinary.com/v2.0/global/all.js"
type="text/javascript"
/>
</Head>
{children({ open })}
</>
);
}
7 changes: 6 additions & 1 deletion components/Date.js → components/Date.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { parseISO, format } from "date-fns";

export default function Date({ dateString }) {
interface DateProps {
dateString: string;
}

export default function Date({ dateString }: DateProps) {
const date = parseISO(dateString);

return <time dateTime={dateString}>{format(date, "LLL d, yyyy")}</time>;
}
12 changes: 10 additions & 2 deletions components/Logo.js → components/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
const Logo = (props) => {
import type { WithClassName } from "@/types";

interface LogoProps extends WithClassName {
color: string;
height?: number;
width: number;
}

const Logo = (props: LogoProps) => {
return (
<svg
className={props.className}
Expand All @@ -7,7 +15,7 @@ const Logo = (props) => {
height={props.height || 23}
viewBox="0 0 162 23"
>
<title>DAO Jones Logo</title>
<title>Platforms Starter Kit Logo</title>
<g fill="none" fillRule="evenodd" stroke="none" strokeWidth="1">
<g fill={props.color || "#000"} fillRule="nonzero">
<path d="M0 23V1h7.8C15.35 1 19 5.714 19 12.031 19 18.317 15.35 23 7.8 23H0zm4-4h2.87c5.124 0 7.13-3 7.13-6.969C14 8.062 11.994 5 6.87 5H4v14zm13 4l9.092-22h3.847L39 23h-4.832l-1.526-4.18h-9.284L21.832 23H17zm8-9h6l-2.25-5.638A16.62 16.62 0 0128 6c-.21.797-.45 1.624-.75 2.362L25 14zm23.532 9C41.96 23 37 17.868 37 11.532 37 5.164 41.96 0 48.532 0 55.072 0 60 5.164 60 11.532 60 17.868 55.071 23 48.532 23zM42 11.532C42 15.62 44.493 19 48.53 19c4.007 0 6.47-3.38 6.47-7.468S52.537 4 48.53 4C44.493 4 42 7.444 42 11.532zM76.008 23C69.735 23 65 17.868 65 11.532 65 5.164 69.494 0 76.008 0c3.438 0 5.82 1.109 7.72 3.485l-2.985 2.724c-1.267-1.394-2.835-2.09-4.735-2.09-4.071 0-6.635 3.358-6.635 7.413s2.564 7.35 6.725 7.35c2.051 0 3.59-.73 4.826-2.155L84 19.483C82.402 21.511 79.687 23 76.008 23zm17.067 0C88.242 23 85 19.201 85 14.531S88.392 6 93.075 6 101 9.86 101 14.531c0 .467-.03.965-.12 1.495H89.203c.45 1.899 1.83 3.238 3.872 3.238a4.339 4.339 0 003.812-2.18l3.152 2.46C98.78 21.568 96.167 23 93.075 23zM89 13h8c-.467-1.657-1.992-3-4.047-3-1.992 0-3.486 1.229-3.953 3zm14 9V6.36h4.071v2.287C107.898 6.902 109.49 6 111.94 6 115.367 6 118 8.496 118 12.436V22h-4.133v-8.571c0-2.707-1.377-3.88-3.428-3.88-1.745 0-3.306 1.173-3.306 3.88V22H103zm23.296 1c-3.24 0-5-1.502-5-5.04v-7.636H119v-3.6h2.296V3.439L125.54 3v3.725H129v3.599h-3.46v7.418c0 1.033.504 1.502 1.322 1.502h1.76V23h-2.326zM130 22V6.373h4.038v2.975c.554-2.254 2.188-3.486 4.962-3.336V9.83h-.586c-2.404 0-4.253 1.563-4.253 4.177V22H130zm16.858 1c-4.372 0-7.858-3.781-7.858-8.469C139 9.844 142.486 6 146.858 6c2.752 0 4.189 1.156 5.045 2.906V6.344H156v16.25h-4.005v-2.657C151.138 21.782 149.7 23 146.858 23zM143 14.5c0 2.37 1.8 4.5 4.469 4.5 2.762 0 4.531-2.04 4.531-4.47 0-2.43-1.769-4.53-4.531-4.53C144.8 10 143 12.07 143 14.5zm16 8.5V0h4v23h-4z"></path>
Expand Down
11 changes: 9 additions & 2 deletions components/LogoSmall.js → components/LogoSmall.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
const LogoSmall = (props) => {
import type { WithClassName } from "@/types";

interface LogoSmallProps extends WithClassName {
height?: number;
width: number;
}

const LogoSmall = (props: LogoSmallProps) => {
return (
<svg
className={props.className}
Expand All @@ -7,7 +14,7 @@ const LogoSmall = (props) => {
height={props.height || 25}
viewBox="0 0 40 25"
>
<title>DAO Jones Logo (Small)</title>
<title>Platforms Starter Kit Logo (Small)</title>
<g fill="#000" fillRule="evenodd" stroke="none" strokeWidth="1">
<path d="M30.746 25C23.483 25 18 19.421 18 12.534 18 5.613 23.203 0 30.746 0 34.727 0 37.8 1.137 40 3.72c-.328.375-.717.901-1.165 1.577a9.121 9.121 0 00-1.015 1.976c-1.467-1.515-4.874-2.796-7.074-2.796-4.714 0-7.683 3.65-7.683 8.057 0 4.408 2.969 7.99 7.788 7.99 2.374 0 5.607-1.128 7.039-2.677.411.91.726 1.538.945 1.883.25.396.639.878 1.165 1.448C38.15 23.382 35.006 25 30.746 25z"></path>
<path d="M0 24V1h8.21C16.158 1 20 5.929 20 12.533 20 19.104 16.158 24 8.21 24H0zm4.598-4.14h3.054c5.451 0 7.586-3.154 7.586-7.327S13.103 5.14 7.652 5.14H4.598v14.72z"></path>
Expand Down
13 changes: 12 additions & 1 deletion components/Modal.js → components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Dialog, Transition } from "@headlessui/react";
import { Fragment } from "react";

export default function Modal({ children, showModal, setShowModal }) {
import type { WithChildren } from "@/types";

interface ModalProps extends WithChildren {
showModal: boolean;
setShowModal: (state: boolean) => void;
}

export default function Modal({
children,
showModal,
setShowModal,
}: ModalProps) {
return (
<>
<Transition appear show={showModal} as={Fragment}>
Expand Down
38 changes: 29 additions & 9 deletions components/app/DomainCard.js → components/app/DomainCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import useSWR, { mutate } from "swr";
const fetcher = (...args) => fetch(...args).then((res) => res.json());
import { useState } from "react";
import LoadingDots from "@/components/app/loading-dots";
import { fetcher } from "@/lib/fetcher";
import { HttpMethod } from "@/types";

const DomainCard = ({ data, setData }) => {
const { data: valid, isValidating } = useSWR(
`/api/check-domain?domain=${data.customDomain}`,
import type { Site } from "@prisma/client";

type DomainData = Pick<
Site,
| "customDomain"
| "description"
| "id"
| "image"
| "imageBlurhash"
| "name"
| "subdomain"
>;

interface DomainCardProps<T = DomainData> {
data: T;
setData: (data: T) => void;
}

export default function DomainCard({ data, setData }: DomainCardProps) {
const { data: valid, isValidating } = useSWR<Site>(
`/api/domain/check?domain=${data.customDomain}`,
fetcher,
{ revalidateOnMount: true, refreshInterval: 5000 }
);
Expand Down Expand Up @@ -42,7 +61,7 @@ const DomainCard = ({ data, setData }) => {
<div className="flex space-x-3">
<button
onClick={() => {
mutate(`/api/check-domain?domain=${data.customDomain}`);
mutate(`/api/domain/check?domain=${data.customDomain}`);
}}
disabled={isValidating}
className={`${
Expand All @@ -57,7 +76,10 @@ const DomainCard = ({ data, setData }) => {
onClick={async () => {
setRemoving(true);
await fetch(
`/api/remove-domain?domain=${data.customDomain}&siteId=${data.id}`
`/api/domain?domain=${data.customDomain}&siteId=${data.id}`,
{
method: HttpMethod.DELETE,
}
).then((res) => {
setRemoving(false);
if (res.ok) {
Expand Down Expand Up @@ -167,6 +189,4 @@ const DomainCard = ({ data, setData }) => {
)}
</div>
);
};

export default DomainCard;
}
Loading

0 comments on commit 327dfa1

Please sign in to comment.