Skip to content

Commit

Permalink
feat(homepage): add surau form
Browse files Browse the repository at this point in the history
  • Loading branch information
farhan-helmy committed Mar 1, 2023
1 parent 95f0d57 commit 61c25d0
Show file tree
Hide file tree
Showing 9 changed files with 1,247 additions and 20 deletions.
3 changes: 2 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const config = {
hostname: "api.dicebear.com",
},
],
dangerouslyAllowSVG: true
domains: ["ratemysurau.s3.ap-southeast-1.amazonaws.com"],
dangerouslyAllowSVG: true,
},
};
export default config;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@trpc/server": "^10.9.0",
"next": "13.1.6",
"next-auth": "^4.19.0",
"next-s3-upload": "^0.3.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-select": "^5.7.0",
Expand Down
140 changes: 135 additions & 5 deletions src/components/AddSurauForm.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/* eslint-disable @typescript-eslint/restrict-plus-operands */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import { PhotoIcon, PlusCircleIcon } from '@heroicons/react/20/solid';
import dynamic from 'next/dynamic'
import type { FC} from 'react';
import { useEffect, useState } from 'react'
import type { FC } from 'react';
import React, { useEffect, useState } from 'react'
import { useS3Upload } from 'next-s3-upload';
import Image from 'next/image'
const Select = dynamic(() => import("react-select"), {
ssr: true,
})
Expand Down Expand Up @@ -30,23 +37,87 @@ export type AddSurauFormProps = {
setOpen: (open: boolean) => void
}

export type ImagePreviews = {
id: string,
url: string
}

const AddSurauForm: FC<AddSurauFormProps> = ({ open, setOpen }) => {

const [state, setState] = useState<State[]>([]);
const [district, setDistrict] = useState<[]>([]);
const [choosenState, setChoosenState] = useState("");
const [imagePreviews, setImagePreviews] = useState<ImagePreviews[]>();
const [loading, setLoading] = useState(false);

const { uploadToS3 } = useS3Upload();

const handleNegeriChange = (e: any) => {

setLoading(true)
setTimeout(() => {
setLoading(false)
}, 1000)
const negeri = e.state as string
void fetch(`https://jianliew.me/malaysia-api/state/v1/${negeri.toLowerCase()}.json`)
.then(res => res.json())
.then(data => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const daerah: any = []

data.administrative_districts.forEach((item: any) => {
daerah.push({
label: item,
value: item
})
})
console.log(daerah)

setDistrict(daerah)
})
console.log(district)
}

const handleAddMoreImages = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files === null) return;
const file = e.target?.files[0];
const { url } = await uploadToS3(file as File);

setImagePreviews([...imagePreviews as ImagePreviews[], URL.createObjectURL(file as Blob) as unknown as ImagePreviews]);
console.log(imagePreviews)
}

const onProductImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {

const images: ImagePreviews[] = [];
const urls: string[] = [];

if (e.target.files === null) return;

for (const element of e.target.files) {
images.push(URL.createObjectURL(element as Blob) as unknown as ImagePreviews);
const { url } = await uploadToS3(element);
urls.push(url);
}
console.log(urls)
setImagePreviews(images);
// const { url } = await uploadToS3(file);
// setValue('image', urls.map(url => ({ src: url })));
}


useEffect(() => {
void fetch("https://jianliew.me/malaysia-api/state/v1/all.json")
.then(res => res.json())
.then(data => {
console.log(data)
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
setState(data)
})
}, [])

return (
<>
<div className="">
<div className="h-full">
<div className="md:grid md:grid-cols-2 md:gap-6">
<div className="md:col-span-1">
<div className="px-4 sm:px-0">
Expand Down Expand Up @@ -81,15 +152,35 @@ const AddSurauForm: FC<AddSurauFormProps> = ({ open, setOpen }) => {
<label htmlFor="surau-name" className="block text-sm font-medium text-gray-700">
State
</label>
<div className="mt-1 block rounded-md shadow-sm w-full">
<div className="mt-1 block rounded-md shadow-sm w-full relative z-10">
<Select
options={state}
getOptionLabel={(option: any) => option.state}
getOptionValue={(option: any) => option.state}
onChange={(e) => handleNegeriChange(e)}
/>
</div>
</div>
</div>
{loading ? (
<div className="flex justify-center items-center">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-gray-900"></div>
</div>
) : null}

{!loading && district.length !== 0 ? (
<div className="grid grid-cols-3 gap-6">
<div className="col-span-2 sm:col-span-2">
<label htmlFor="surau-name" className="block text-sm font-medium text-gray-700">
District
</label>
<div className="mt-1 block rounded-md shadow-sm w-full relative z-0">
<Select
options={district}
/>
</div>
</div>
</div>) : null}
<div>
<label htmlFor="about" className="block text-sm font-medium text-gray-700">
Direction / guide
Expand All @@ -108,6 +199,45 @@ const AddSurauForm: FC<AddSurauFormProps> = ({ open, setOpen }) => {
</p>
</div>

{!imagePreviews ? (<div className="flex text-sm text-gray-600">
<label
htmlFor="product-image-upload"
className="relative cursor-pointer rounded-md bg-white font-medium text-indigo-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2 hover:text-indigo-500"
>
<div className="group relative m-4">
<PhotoIcon className="h-12 w-12" />
<span className="absolute top-10 scale-0 transition-all rounded bg-gray-800 p-2 text-md text-white group-hover:scale-100">✨ click to add photo!</span>
</div>
<input type="file" name="product-image-upload" id="product-image-upload" className="sr-only" onChange={(e) => void onProductImageChange(e)} multiple accept="image/*" />
</label>
</div>)
: null}

<div className="">
<div className="grid-cols-2 p-4 space-y-2 grid gap-2">
{imagePreviews ? (
imagePreviews.map((imagePreview, index) => (
<div key={index}>
<h1>{imagePreview.url}</h1>
<Image src={imagePreview as unknown as string} alt="xsd" sizes='100vw' width={250} height={250} />
</div>
))) : null}
{imagePreviews ? (
<div className="flex flex-col justify-center items-center border border-b rounded-lg h-32">
<label
htmlFor="add-more-product-image-upload"
className="relative cursor-pointer rounded-md bg-white font-medium text-indigo-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2 hover:text-indigo-500"
>
<span>
<PlusCircleIcon className="h-5 w-5" aria-hidden="true" />
</span>
<input type="file" name="add-more-product-image-upload" id="add-more-product-image-upload" className="sr-only" onChange={(e) => void handleAddMoreImages(e)} multiple accept="image/*" />
</label>
</div>
) : null}
</div>
</div>


</div>
<div className="bg-gray-50 px-4 py-3 text-right sm:px-6 flex flex-row items-end justify-end gap-2">
Expand Down
7 changes: 3 additions & 4 deletions src/components/AddSurauFormModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { FC} from 'react';
import { Fragment, useState } from 'react'
import { Fragment } from 'react'
import { Dialog, Transition } from '@headlessui/react'
import { CheckIcon } from '@heroicons/react/24/outline'
import type { AddSurauFormProps } from './AddSurauForm';
import AddSurauForm from './AddSurauForm'

Expand All @@ -23,7 +22,7 @@ const AddSurauFormModal: FC<AddSurauFormModalProps> = ({open, setOpen}) => {
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="fixed inset-0 z-0 overflow-y-auto">
<div className="flex items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
Expand All @@ -34,7 +33,7 @@ const AddSurauFormModal: FC<AddSurauFormModalProps> = ({open, setOpen}) => {
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-4xl sm:p-6">
<Dialog.Panel className="relative transform rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-4xl sm:p-6">
<div>
<AddSurauForm setOpen={setOpen} open />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReviewSurauForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StarIcon } from "@heroicons/react/20/solid";
import Image from "next/image";
import { FC, useEffect } from "react";
import type { FC } from "react";
import { useState } from "react"


Expand Down
7 changes: 7 additions & 0 deletions src/components/SignInForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const SignInForm = () => {
return (
<div>
SignIn
</div>
)
}
1 change: 1 addition & 0 deletions src/pages/api/s3-upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { APIRoute as default } from "next-s3-upload";
13 changes: 9 additions & 4 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import Link from 'next/link'
import SurauList from '../components/SurauList'
import Image from 'next/image'
import Head from 'next/head'
import AddSurauFormModal from '../components/AddSurauFormModal'
import { useState } from 'react'


const collections = [
Expand Down Expand Up @@ -82,7 +84,10 @@ function classNames(...classes: any) {
return classes.filter(Boolean).join(' ')
}

export default function Example() {
export default function Index() {

const [openAddSurauForm, setOpenAddSurauForm] = useState(false)

return (
<>
<Head>
Expand Down Expand Up @@ -165,16 +170,16 @@ export default function Example() {
placeholder="Search for a Surau"
className="mt-8 rounded-md border border-transparent bg-white py-3 w-full px-2 text-base font-medium text-gray-900 hover:bg-gray-100"
/>

<p className="font-extralight text-white text-xs mt-2 md:text-lg italic">Can`t find your Surau? <span className="underline" onClick={() => setOpenAddSurauForm(true)}>Add here</span></p>
</div>
</div>

<AddSurauFormModal open={openAddSurauForm} setOpen={setOpenAddSurauForm} />
<main>
{/* Category section */}
<section aria-labelledby="category-heading" className="pt-12 sm:pt-12 xl:mx-auto xl:max-w-7xl xl:px-8">
<div className="mx-auto flex max-w-3xl flex-col items-center text-center">
<h2 id="category-heading" className="text-2xl font-bold tracking-tight text-gray-900">
Recently reviewed surau
Recently reviewed
</h2>
</div>
<SurauList />
Expand Down
Loading

0 comments on commit 61c25d0

Please sign in to comment.