Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate user and group services to frontend #28

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
9 changes: 6 additions & 3 deletions hono/src/services/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { env } from 'hono/adapter'
import { groups, posts, prompts, usersToGroups } from '../schema'
import type { Variables } from '../utils/inject-db'
import injectDB from '../utils/inject-db'
import type { GroupType, CloudflareResponse, Post } from '../utils/type-definitions'
import type { CloudflareResponse, GroupType, Post } from '../utils/type-definitions'

const app = new Hono<{ Variables: Variables }>()

Expand Down Expand Up @@ -122,8 +122,11 @@ app.post('/post', injectDB, async (c) => {
const resJson = (await response.json()) as CloudflareResponse
const photo_url = resJson.result.variants[4]

const userId = body.get('userId')
const postBody = { userId, photoUrl: photo_url, timestamp: new Date() } as Post
const postBody = {
userId: body.get('userId'),
photoUrl: photo_url,
timestamp: new Date(),
} as Post
return c.json((await c.get('db').insert(posts).values(postBody).returning())[0])
})

Expand Down
92 changes: 0 additions & 92 deletions hono/test/smoke/user.smoke.test.ts

This file was deleted.

3 changes: 3 additions & 0 deletions next/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ if (process.env.NODE_ENV === 'development') {
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ['imagedelivery.net'],
},

webpack: (config, { isServer }) => {
if (!isServer) {
Expand Down
76 changes: 53 additions & 23 deletions next/src/app/components/FeedInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
"use client";
import { useState } from "react";
import { useState, useEffect } from "react";
import LineChart from "../charts/LineChart";
import HomeDropdown from "./HomeDropdown";
import Image from 'next/image';
import WeUpLogo from '../assets/weup.png';

export default function FeedInfo({ isUp, handleClick }: { isUp: any, handleClick: any }) {

const handleImageUpload = (event: { target: { files: any[]; }; }) => {
const file = event.target.files[0];
if (file) {
handleClick();
}
};
const [imageSrcs, setImageSrcs] = useState([]);

useEffect(() => {
const fetchImage = async () => {
try {
const response = await fetch("http://127.0.0.1:8787/api/group/rsf9kxfvz4dauvggv47wbf0c");
const data = await response.json();
const posts = data.post;

const photoUrls = posts.map(post => post.photoUrl).filter(url => url !== undefined);

if (photoUrls.length > 0) {
setImageSrcs(photoUrls); // Set the found photoUrls array
} else {
console.error("No posts found or posts have no photoUrl");
}
} catch (error) {
console.error("Failed to fetch image:", error);
}
};

if (isUp) {
fetchImage();
}
}, [isUp]);
return (
<>
{/* Fixed upload button */}
Expand All @@ -23,22 +41,34 @@ export default function FeedInfo({ isUp, handleClick }: { isUp: any, handleClick
</button>
</div>

<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<label htmlFor="dropzone-file" className="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
{isUp ? (
<Image src={WeUpLogo} className="w-full h-64 object-cover rounded-lg" alt={''} />
) : (
<div className="flex flex-col items-center justify-center pt-5 pb-6">
<svg className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400"><span className="font-semibold">Click to upload</span> or drag and drop</p>
<p className="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
</div>
)}
<input id="dropzone-file" type="file" className="hidden"/>
</label>
</div>
<div className="container mx-auto px-4 sm:px-6 lg:px-8 mt-4 mb-4">
{isUp ? (
<div className="grid gap-4">
{imageSrcs.map((src, index) => (
<div key={index} className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
<Image
src={src}
layout="responsive"
width={700} // replace with the actual aspect ratio of the images
height={400} // replace with the actual aspect ratio of the images
objectFit="cover"
alt={`Image ${index}`}
/>
</div>
))}
</div>
) : (
// Fallback or placeholder content
<div className="flex flex-col items-center justify-center pt-5 pb-6">
<svg className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400"><span className="font-semibold">Click to upload</span> or drag and drop</p>
<p className="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
</div>
)}
</div>
{/* <input id="dropzone-file" type="file" className="hidden"/> */}
<div className="pt-4">
<div>
<h1 className="lowercase text-center my-6 text-2xl sm:text-3xl md:text-5xl lg:text-6xl font-semibold leading-none tracking-tight text-gray-900 dark:text-white">Today&apos;s <mark className="px-2 text-white bg-blue-600 rounded dark:bg-blue-500">Feed</mark></h1>
Expand Down
2 changes: 1 addition & 1 deletion next/src/app/home2/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function Home2() {
{/* Group Info */}
<GroupInfo />
{/* Feed */}
<FeedInfo isUp={isUp} handleClick={handleClick}/>
<FeedInfo isUp={true} handleClick={handleClick}/>
</div>
</div>

Expand Down
42 changes: 42 additions & 0 deletions next/src/app/upload/FileUploadComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client';
import React from 'react';
import Image from 'next/image';
import WeUpLogo from '../assets/weup.png';
import { uploadImageToCloudflare } from './imageUpload';

const FileUploadComponent = ({ userId }) => {

const handleFileChange = async (event) => {
const file = event.target.files[0];
if (file) {
try {
await uploadImageToCloudflare(file, userId); // Use 'ldfm1lck9gcytdfju6b8dgjd' if needed
console.log('Upload successful');
alert('Upload successful');
} catch (error) {
console.error('Error uploading image:', error);
alert('Error uploading image');
}
} else {
console.error('No file selected');
alert('No file selected');
}
};

return (
<div className="my-4 flex items-center justify-center w-full">
<label htmlFor="dropzone-file" className="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
<div className="flex flex-col items-center justify-center pt-5 pb-6">
<svg className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400"><span className="font-semibold">Click to upload</span> or drag and drop</p>
<p className="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
</div>
<input id="dropzone-file" type="file" className="hidden" onChange={handleFileChange} />
</label>
</div>
);
};

export default FileUploadComponent;
9 changes: 2 additions & 7 deletions next/src/app/upload/imageUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import FormData from 'form-data';
import fetch from 'node-fetch';

export async function uploadImageToCloudflare(file: File, userId: String) {
export async function uploadImageToCloudflare(file, userId) {
const formData = new FormData();
formData.append("file", file);
formData.append("userId", userId)

const headers = formData.getHeaders();

try {
const response = await fetch('http://127.0.0.1:8787/api/group/post', {
method: 'POST',
body: formData,
headers: headers,
});

if (!response.ok) {
Expand All @@ -26,4 +21,4 @@ export async function uploadImageToCloudflare(file: File, userId: String) {
console.error('Error uploading image:', error);
alert('Error uploading image');
}
}
}
50 changes: 6 additions & 44 deletions next/src/app/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,16 @@
"use client";
import React, { Component, useState } from 'react';
import WeUpLogo from '../assets/weup.png';
import Image from 'next/image';
import HomeDropdown from '../components/HomeDropdown';
import {uploadImageToCloudflare} from './imageUpload';
import {withPageAuthRequired, getSession} from '@auth0/nextjs-auth0/edge';
import {getUserAPI} from '../../util/api-helpers'
import { User } from '../../../../hono/src/utils/type-definitions'
import FileUploadComponent from './FileUploadComponent';

export default withPageAuthRequired(async function Upload() {
const session = await getSession()
const user = (await getUserAPI(session?.user.email)) as User
const [selectedFile, setSelectedFile] = useState<File | null>(null);


const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files && event.target.files.length > 0) {
const file = event.target.files[0];
setSelectedFile(file);
} else {
console.log("No file selected or 'files' is null");
setSelectedFile(null);
}
if (selectedFile) {
try {
await uploadImageToCloudflare(selectedFile, user.id) // replace with userId string if needed
console.log('Upload successful');
alert('Upload successful');
} catch (error) {
console.error('Error uploading image:', error);
alert('Error uploading image');
}
} else {
console.error('No file selected');
alert('No file selected');
}
};
export default async function Upload() {
// const session = await getSession();
// const user = await getUserAPI(session?.user.email);

return (
<>
Expand All @@ -56,18 +31,7 @@ export default withPageAuthRequired(async function Upload() {
</div>

{/* Upload function */}
<div className="my-4 flex items-center justify-center w-full">
<label htmlFor="dropzone-file" className="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
<div className="flex flex-col items-center justify-center pt-5 pb-6">
<svg className="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
</svg>
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400"><span className="font-semibold">Click to upload</span> or drag and drop</p>
<p className="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
</div>
<input id="dropzone-file" type="file" className="hidden" onChange={handleFileChange} />
</label>
</div>
<FileUploadComponent userId={"igk3t7lx2projnzyxqwvty4t"} />

<p className="text-sm font-normal py-2.5 text-center text-gray-900 dark:text-white">Take a picture with your breakfast!</p>
<div className="flex my-1 space-x-1 justify-center">
Expand Down Expand Up @@ -111,6 +75,4 @@ export default withPageAuthRequired(async function Upload() {

</>
);
}, {returnTo: '/profile'})

export const runtime = 'edge';
}
2 changes: 1 addition & 1 deletion next/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
, "src/app/upload/FileUploadComponent.jsx" ],
"exclude": [
"node_modules"
]
Expand Down
Loading