Skip to content

Commit

Permalink
Configuration of Firebase Storage Bucket
Browse files Browse the repository at this point in the history
Using Firbase storageBucket to save the upload images to the server
  • Loading branch information
IslamiTP committed Nov 27, 2024
1 parent bbdd93d commit db31493
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 85 deletions.
3 changes: 2 additions & 1 deletion .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 73 additions & 32 deletions src/app/portfolio/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
'use client';

import React, { useRef, useState } from 'react';
import { useRouter } from 'next/navigation';
import './portfolio.css';
import { useRouter } from 'next/navigation';
import React, { useRef, useState } from 'react';
import Navbar from '../components/navigationbar';
import { storage } from '../../firebase-config'; // Import Firebase storage
import { ref, uploadBytes, getDownloadURL } from 'firebase/storage';
import SocialMediaInput from '../components/socialmediainput'; // Default import (no curly braces)


export default function Portfolio() {
const [businessName, setBusinessName] = useState('');
const [bio, setBio] = useState('');
const [profilePicture, setProfilePicture] = useState<File | null>(null);
const [profilePictureUrl, setProfilePictureUrl] = useState<string | null>(null);
const [photos, setPhotos] = useState<File[]>([]);
const [photoUrls, setPhotoUrls] = useState<string[]>([]);
const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0);
const [services, setServices] = useState([{ name: '', price: '', time: '' }]);
const [showBusinessHours, setShowBusinessHours] = useState(false);
Expand All @@ -25,20 +30,33 @@ export default function Portfolio() {
const profileInputRef = useRef<HTMLInputElement>(null);
const router = useRouter();

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

//----------------------------- Photo Upload Section ----------------------------------------------------------

// Handle profile picture upload
const handleProfilePictureUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setProfilePicture(e.target.files[0]);
const file = e.target.files[0];
setProfilePicture(file);

// Upload to Firebase
const url = await uploadToFirebase(file, 'profile_pictures');
setProfilePictureUrl(url);
}
};

const triggerProfileUpload = () => {
profileInputRef.current?.click();
};

const handlePhotoUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
// Handle carousel photos upload
const handlePhotoUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
const newPhotos = Array.from(e.target.files);
setPhotos(newPhotos);
const files = Array.from(e.target.files);
setPhotos(files);

// Upload each photo to Firebase
const urls = await Promise.all(files.map((file) => uploadToFirebase(file, 'carousel_photos')));
setPhotoUrls(urls);
setCurrentPhotoIndex(0);
}
};
Expand All @@ -51,6 +69,16 @@ export default function Portfolio() {
setCurrentPhotoIndex((prevIndex) => (prevIndex - 1 + photos.length) % photos.length);
};


// Function to upload file to Firebase Storage
const uploadToFirebase = async (file: File, path: string): Promise<string> => {
const storageRef = ref(storage, `${path}/${file.name}`);
await uploadBytes(storageRef, file);
return getDownloadURL(storageRef);
};


// Service Functions
const handleServiceChange = (index: number, field: string, value: string) => {
const updatedServices = [...services];
updatedServices[index] = { ...updatedServices[index], [field]: value };
Expand All @@ -66,36 +94,35 @@ export default function Portfolio() {
setServices(updatedServices);
};


// ------------------------------------------------------ Social Links ------------------------------------------------------
const handleSocialLinkChange = (index: number, field: string, value: string) => {
const updatedLinks = [...socialLinks];
updatedLinks[index] = { ...updatedLinks[index], [field]: value };
setSocialLinks(updatedLinks);
};
// ------------------------------------------------------------------------------------------------------------

// Handle form submission
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData();
formData.append('business_name', businessName);
formData.append('bio', bio);
if (profilePicture) formData.append('profile_picture', profilePicture);
photos.forEach((photo, index) => {
formData.append(`photos[${index}]`, photo);
});
services.forEach((service, index) => {
formData.append(`services[${index}][name]`, service.name);
formData.append(`services[${index}][price]`, service.price);
formData.append(`services[${index}][time]`, service.time);
});
socialLinks.forEach((link, index) => {
formData.append(`socialLinks[${index}][platform]`, link.platform);
formData.append(`socialLinks[${index}][url]`, link.url);
});

const formData = {
business_name: businessName,
bio,
profile_picture: profilePictureUrl,
photos: photoUrls,
services,
social_links: socialLinks
};

try {
const response = await fetch('http://localhost:8000/api/artist-portfolio/', {
method: 'POST',
body: formData,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});

if (response.ok) {
alert('Portfolio saved successfully!');
router.push('/appointments');
Expand All @@ -109,6 +136,9 @@ export default function Portfolio() {
}
};


// ------------------------------------------------------ Business Hour ------------------------------------------------------

const toggleBusinessHours = () => {
setShowBusinessHours(!showBusinessHours);
};
Expand All @@ -132,9 +162,15 @@ export default function Portfolio() {
setShowBusinessHours(false);
};




// ------------------------------------------------------ HMTL SECTION ------------------------------------------------------
return (
<div className="container">
<Navbar />

{/* Business Name */}
<div className="business-name">
<input
type="text"
Expand All @@ -157,10 +193,10 @@ export default function Portfolio() {
style={{ display: 'none' }}
/>
<div className="relative w-full h-full">
{profilePicture ? (
{profilePictureUrl ? (
<img
className="w-full h-full rounded-full object-cover"
src={URL.createObjectURL(profilePicture)}
src={profilePictureUrl}
alt="Profile"
/>
) : (
Expand All @@ -176,12 +212,13 @@ export default function Portfolio() {
</div>
</div>

{/* Carousel Photo Upload */}
<div id="default-carousel" className="relative w-full" data-carousel="slide">
<div className="relative h-[500px] w-[900px] overflow-hidden rounded-lg group">
{photos.length > 0 ? (
{photoUrls.length > 0 ? (
<div className="duration-700 ease-in-out">
<img
src={URL.createObjectURL(photos[currentPhotoIndex])}
src={photoUrls[currentPhotoIndex]}
className="absolute block w-full -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2"
alt={`Carousel ${currentPhotoIndex}`}
/>
Expand Down Expand Up @@ -209,6 +246,9 @@ export default function Portfolio() {
</label>
</div>

{/* Carousel Controls */}

{/* Carousel Previous Photo */}
<button
type="button"
onClick={handlePrevPhoto}
Expand All @@ -227,6 +267,7 @@ export default function Portfolio() {
</span>
</button>

{/* Carousel Next Photo */}
<button
type="button"
onClick={handleNextPhoto}
Expand All @@ -246,13 +287,13 @@ export default function Portfolio() {
</button>
</div>

{/* About Section */}
{/* Information Section */}
<div className="description-wrapper">
<h2>About</h2>
<h2>More Information</h2>
<textarea
value={bio}
onChange={(e) => setBio(e.target.value)}
placeholder="Write a short description"
placeholder="List information about booking Here. For instance the address or any heads that a customer might need for parking."
/>
</div>

Expand Down
94 changes: 51 additions & 43 deletions src/app/userprofile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

/* eslint-disable @typescript-eslint/no-unused-vars */

'use client';

import { useRouter } from 'next/navigation';
import { useState, useRef, useEffect } from 'react';
import { auth } from '../firebase';
import { storage } from '../../firebase-config'; // Import Firebase storage
import { ref, uploadBytes, getDownloadURL } from 'firebase/storage';
import React from 'react';

export default function UserProfile() {
Expand All @@ -14,49 +13,27 @@ export default function UserProfile() {
const [city, set_city] = useState('');
const [phone_number, set_phone_number] = useState('');
const [prof_pic, set_profpic] = useState<File | null>(null);
const [prof_pic_preview, set_profpic_preview] = useState<string | null>(null);
const [prof_pic_url, set_profpic_url] = useState<string | null>(null); // Store Firebase URL

const profileInputRef = useRef<HTMLInputElement>(null);
const router = useRouter();

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData();
formData.append('fullname', fullname);
formData.append('email', email);
formData.append('city', city);
formData.append('phone_number', phone_number);
if (prof_pic) {
formData.append('profile_picture', prof_pic);
}

try {
const response = await fetch('http://localhost:8000/api/user-profile/', {
method: 'POST',
body: formData,
});
if (response.ok) {
alert('Profile saved successfully!');
} else {
const errorData = await response.json();
alert(`Error: ${errorData.detail}`);
}
} catch (error) {
console.error('Error saving profile:', error);
alert('An unexpected error occurred. Please try again.');
}
// Upload to Firebase Storage
const uploadToFirebase = async (file: File, path: string): Promise<string> => {
const storageRef = ref(storage, `${path}/${file.name}`);
await uploadBytes(storageRef, file);
return getDownloadURL(storageRef);
};

const handleLogout = () => {
alert('Logging out...');
router.push('/login');
};

const handleProfilePictureUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
// Handle profile picture upload
const handleProfilePictureUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files[0]) {
const file = e.target.files[0];
set_profpic(file);
set_profpic_preview(URL.createObjectURL(file));

// Upload to Firebase and set URL
const url = await uploadToFirebase(file, 'profile_pictures');
set_profpic_url(url);
}
};

Expand All @@ -67,14 +44,45 @@ export default function UserProfile() {
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
set_email(user.email || '');
set_fullname(user.displayName || '');
set_email(user.email || '');
set_fullname(user.displayName || '');
}
});

return () => unsubscribe();
}, []);

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();

// Data to be sent to backend
const payload = {
fullname,
email,
city,
phone_number,
profile_picture: prof_pic_url // Use the Firebase URL
};

try {
const response = await fetch('http://localhost:8000/api/user-profile/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});

if (response.ok) {
alert('Profile saved successfully!');
} else {
const errorData = await response.json();
alert(`Error: ${errorData.detail}`);
}
} catch (error) {
console.error('Error saving profile:', error);
alert('An unexpected error occurred. Please try again.');
}
};

return (
<div className="min-h-screen flex flex-col items-center justify-center bg-gray p-6">
<div className="container max-w-4xl p-12 bg-white border-4 border-[#f4d9a0] shadow-lg rounded-lg text-center">
Expand All @@ -91,10 +99,10 @@ export default function UserProfile() {
style={{ display: 'none' }}
/>
<div className="relative w-24 h-24 cursor-pointer">
{prof_pic_preview ? (
{prof_pic_url ? (
<img
className="w-full h-full rounded-full object-cover"
src={prof_pic_preview}
src={prof_pic_url}
alt="Profile"
/>
) : (
Expand Down Expand Up @@ -167,4 +175,4 @@ export default function UserProfile() {
</div>
</div>
);
}
}
Loading

0 comments on commit db31493

Please sign in to comment.