.Profile Page
This commit is contained in:
32
src/app/(app)/profile/page.tsx
Normal file
32
src/app/(app)/profile/page.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
export default function ProfilePage() {
|
||||||
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
||||||
|
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
|
||||||
|
const [uploadMessage, setUploadMessage] = useState<string>("");
|
||||||
|
|
||||||
|
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (event.target.files && event.target.files[0]) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
setSelectedFile(file);
|
||||||
|
setPreviewUrl(URL.createObjectURL(file)); // Generate a preview URL for the image
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex flex-col items-center mt-10">
|
||||||
|
<h1 className="text-3xl font-bold mb-6">Profile Picture</h1>
|
||||||
|
<div className="flex flex-col items-center gap-4">
|
||||||
|
{(
|
||||||
|
<img
|
||||||
|
alt="Profile Preview"
|
||||||
|
className="w-32 h-32 rounded-full object-cover border border-gray-300"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{uploadMessage && <p className="text-sm text-gray-600">{uploadMessage}</p>}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
49
src/app/(app)/shop/page.tsx
Normal file
49
src/app/(app)/shop/page.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useDevice } from "@/lib/context/DeviceContext";
|
||||||
|
|
||||||
|
function Mobile() {
|
||||||
|
const { isAuthenticated, session } = useDevice();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex flex-col gap-[32px] row-start-2 items-center mt-10">
|
||||||
|
<h1 className="text-3xl sm:text-4xl font-bold tracking-[-.01em] text-center sm:text-left">
|
||||||
|
{isAuthenticated ? `Welcome, ${session.username} !!` : ""}
|
||||||
|
</h1>
|
||||||
|
{isAuthenticated ? (
|
||||||
|
<div>
|
||||||
|
<button type="button" className="btn bg-surface-500">
|
||||||
|
<a href="/auth/logout">Logout</a>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<button type="button" className="btn bg-surface-500">
|
||||||
|
<a href="/auth/login?screen_hint=signup">Sign up</a>
|
||||||
|
</button>
|
||||||
|
<button type="button" className="btn bg-surface-500">
|
||||||
|
<a href="/auth/login?screen_hint=login">Log in</a>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Web() {
|
||||||
|
const { isAuthenticated, session } = useDevice();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex flex-col row-start-2 items-center mt-10">
|
||||||
|
<h1 className="text-3xl sm:text-4xl font-bold tracking-[-.01em] text-center sm:text-left">
|
||||||
|
{isAuthenticated ? `Welcome, ${session.username} !!` : ""}
|
||||||
|
</h1>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const { isMobile, isSafari } = useDevice();
|
||||||
|
if (isMobile && isSafari) return Mobile();
|
||||||
|
else return Web();
|
||||||
|
}
|
||||||
34
src/app/api/index.ts
Normal file
34
src/app/api/index.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import formidable from 'formidable';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
api: {
|
||||||
|
bodyParser: false, // Disable Next.js body parser to handle form data
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
const form = new formidable.IncomingForm();
|
||||||
|
|
||||||
|
form.parse(req, (err, fields, files) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error parsing form data:', err);
|
||||||
|
return res.status(500).json({ error: 'Failed to process form data' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access the uploaded file
|
||||||
|
const file = files.image;
|
||||||
|
if (file) {
|
||||||
|
console.log('Uploaded file:', file);
|
||||||
|
return res.status(200).json({ message: 'Image received successfully', file });
|
||||||
|
} else {
|
||||||
|
return res.status(400).json({ error: 'No image file uploaded' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.setHeader('Allow', ['POST']);
|
||||||
|
res.status(405).end(`Method ${req.method} Not Allowed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/components/PostRequestComponent.tsx
Normal file
35
src/components/PostRequestComponent.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
const PostRequestComponent: React.FC = () => {
|
||||||
|
const [responseMessage, setResponseMessage] = useState<string>('');
|
||||||
|
|
||||||
|
const handlePostRequest = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ data: 'Sample data' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
setResponseMessage(data.message);
|
||||||
|
} else {
|
||||||
|
setResponseMessage(`Error: ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setResponseMessage('An error occurred while making the request.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button onClick={handlePostRequest}>Make POST Request</button>
|
||||||
|
<p>Response: {responseMessage}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PostRequestComponent;
|
||||||
Reference in New Issue
Block a user