Updates Hackathon example app to 0.14.0 (#2156)

This commit is contained in:
Mihovil Ilakovac 2024-07-15 16:25:55 +02:00 committed by GitHub
parent 5a92e37345
commit abe17d38bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 44 additions and 33 deletions

View File

@ -1,26 +1,10 @@
app hackathonBetaSubmissions { app hackathonBetaSubmissions {
wasp: { wasp: {
version: "^0.13.0" version: "^0.14.0"
},
db: {
system: PostgreSQL
}, },
title: "Hackathon Submissions" title: "Hackathon Submissions"
} }
entity Submission {=psl
name String @id @unique
email String @unique
github String
description String
twitter String?
country String?
website String?
image String?
approved Boolean @default(false)
createdAt DateTime @default(now())
psl=}
route RootRoute { path: "/", to: MainPage } route RootRoute { path: "/", to: MainPage }
page MainPage { page MainPage {
component: import Main from "@src/MainPage.tsx" component: import Main from "@src/MainPage.tsx"

View File

@ -0,0 +1,21 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Submission {
name String @id @unique
email String @unique
github String
description String
twitter String?
country String?
website String?
image String?
approved Boolean @default(false)
createdAt DateTime @default(now())
}

View File

@ -21,7 +21,7 @@ const Navbar = () => {
function scrollToTargetAdjusted() { function scrollToTargetAdjusted() {
var element = document.getElementById('submission'); var element = document.getElementById('submission');
var headerOffset = 75; var headerOffset = 75;
var elementPosition = element.getBoundingClientRect().top; var elementPosition = element!.getBoundingClientRect().top;
var offsetPosition = elementPosition + window.pageYOffset - headerOffset; var offsetPosition = elementPosition + window.pageYOffset - headerOffset;
window.scrollTo({ window.scrollTo({
@ -42,7 +42,7 @@ const Navbar = () => {
</div> </div>
); );
const SocialIcon = ({ Icon, url }) => ( const SocialIcon = ({ Icon, url }: any) => (
<a <a
href={url} href={url}
target='_blank' target='_blank'

View File

@ -15,7 +15,7 @@ const Projects = () => {
</h2> </h2>
<div className='mt-12 gap-6 lg:grid lg:grid-cols-3'> <div className='mt-12 gap-6 lg:grid lg:grid-cols-3'>
{status === 'success' && projects.length ? ( {status === 'success' && projects.length ? (
projects.map((project) => ( projects.map((project: any) => (
<div key={project.name} className='group relative'> <div key={project.name} className='group relative'>
<div className='relative h-80 w-full overflow-hidden rounded-lg bg-white group-hover:opacity-75 sm:aspect-w-2 sm:aspect-h-1 sm:h-64 lg:aspect-w-1 lg:aspect-h-1'> <div className='relative h-80 w-full overflow-hidden rounded-lg bg-white group-hover:opacity-75 sm:aspect-w-2 sm:aspect-h-1 sm:h-64 lg:aspect-w-1 lg:aspect-h-1'>
<img <img
@ -25,7 +25,7 @@ const Projects = () => {
/> />
</div> </div>
<h3 className='mt-6 text-base font-semibold text-neutral-700'> <h3 className='mt-6 text-base font-semibold text-neutral-700'>
<a href={!!project.website ? '//' + project.website : null} target='_blank' rel='noreferrer'> <a href={!!project.website ? '//' + project.website : undefined} target='_blank' rel='noreferrer'>
<span className='absolute inset-0' /> <span className='absolute inset-0' />
{project.name} {project.name}
</a> </a>

View File

@ -1,5 +1,5 @@
import { submitProject } from "wasp/client/operations"; import { submitProject } from "wasp/client/operations";
import React, { useState } from 'react'; import React, { ChangeEvent, FormEvent, useState } from 'react';
export type Submission = { export type Submission = {
name: string; name: string;
@ -17,13 +17,14 @@ const SubmissionForm = () => {
const [isUploading, setIsUploading] = useState(false); const [isUploading, setIsUploading] = useState(false);
const [imageLink, setImageLink] = useState(''); const [imageLink, setImageLink] = useState('');
const onFileUpload = async (event) => { const onFileUpload = async (event: ChangeEvent<HTMLInputElement>) => {
setIsUploading(true); setIsUploading(true);
const clientId = 'd4ecb4220cf055b' const clientId = 'd4ecb4220cf055b'
const auth = 'Client-ID ' + clientId; const auth = 'Client-ID ' + clientId;
const formData = new FormData(); const formData = new FormData();
formData.append('image', event.target?.files[0]); const files = event.target?.files![0]
formData.append('image', files);
try { try {
const imgur = await fetch('https://api.imgur.com/3/upload', { const imgur = await fetch('https://api.imgur.com/3/upload', {
@ -40,7 +41,7 @@ const SubmissionForm = () => {
if (!json.success) { if (!json.success) {
throw new Error('Image upload failed'); throw new Error('Image upload failed');
} }
setFile(event.target.files[0].name); setFile(files.name);
setImageLink(json.data.link); setImageLink(json.data.link);
} catch (error) { } catch (error) {
console.error('error uploading image'); console.error('error uploading image');
@ -48,17 +49,18 @@ const SubmissionForm = () => {
setIsUploading(false); setIsUploading(false);
}; };
const handleSubmit = async (event) => { const handleSubmit = async (event: FormEvent) => {
event.preventDefault(); event.preventDefault();
const data = new FormData(event.target); const target = event.target as HTMLFormElement
const data = new FormData(target);
const value = Object.fromEntries(data.entries()); const value = Object.fromEntries(data.entries());
delete value['file-upload']; delete value['file-upload'];
value.image = imageLink; value.image = imageLink;
try { try {
await submitProject(value as Submission); await submitProject(value)
alert('Project submitted successfully! It will be visible once it is approved.'); alert('Project submitted successfully! It will be visible once it is approved.');
event.target.reset(); target.reset();
} catch (e) { } catch (e) {
console.error('Error while submitting project', e); console.error('Error while submitting project', e);
alert('Error while submitting project'); alert('Error while submitting project');
@ -190,9 +192,8 @@ const SubmissionForm = () => {
<div className='col-span-6'> <div className='col-span-6'>
<label className='block text-sm font-medium text-gray-700'>Cover photo</label> <label className='block text-sm font-medium text-gray-700'>Cover photo</label>
<div <div
className={`${ className={`${isUploading && 'pointer-events-none opacity-35'
isUploading && 'pointer-events-none opacity-35' } mt-1 flex justify-center rounded-md border-2 border-dashed border-gray-300 px-6 pt-5 pb-6`}
} mt-1 flex justify-center rounded-md border-2 border-dashed border-gray-300 px-6 pt-5 pb-6`}
> >
<div className={`${isUploading && 'animate-pulse'} space-y-1 text-center`}> <div className={`${isUploading && 'animate-pulse'} space-y-1 text-center`}>
<svg <svg

View File

@ -6,7 +6,7 @@ export const submitProject = async (project, context) => {
return newProject; return newProject;
}; };
export const getProjects = async (args, context) => { export const getProjects = async (_args, context) => {
return context.entities.Submission.findMany({ return context.entities.Submission.findMany({
where: { where: {
approved: true, approved: true,

View File

@ -5,6 +5,11 @@
// compiler. Proper TS compiler configuration in Wasp is coming soon :) // compiler. Proper TS compiler configuration in Wasp is coming soon :)
{ {
"compilerOptions": { "compilerOptions": {
"module": "esnext",
"target": "esnext",
// We're bundling all code in the end so this is the most appropriate option,
// it's also important for autocomplete to work properly.
"moduleResolution": "bundler",
// JSX support // JSX support
"jsx": "preserve", "jsx": "preserve",
"strict": true, "strict": true,