Firebase Portfolio Storage

User
Firebase cloud storage for portfolio items title,technologies,image ,description
And then also fetch all portfolio
Assistant
To store and fetch portfolio items in Firebase Cloud Storage and Firestore, follow these steps:

### **1. Set Up Firebase**
– Create a Firebase project in the [Firebase Console](https://console.firebase.google.com/).
– Add Firebase to your web app.
– Install Firebase SDK:

npm install firebase

– Initialize Firebase in your project:

import { initializeApp } from "firebase/app";
  import { getStorage } from "firebase/storage";
  import { getFirestore } from "firebase/firestore";

  const firebaseConfig = {
    apiKey: "YOUR_API_KEY",
    authDomain: "YOUR_AUTH_DOMAIN",
    projectId: "YOUR_PROJECT_ID",
    storageBucket: "YOUR_STORAGE_BUCKET",
    messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
    appId: "YOUR_APP_ID"
  };

  const app = initializeApp(firebaseConfig);
  export const storage = getStorage(app);
  export const db = getFirestore(app);

### **2. Upload Portfolio Item (Title, Technologies, Image, Description)**
– Use Firestore for storing metadata and Firebase Storage for images.

import { getFirestore, collection, addDoc } from "firebase/firestore";
import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";

const db = getFirestore();
const storage = getStorage();

const uploadPortfolioItem = async (title, technologies, imageFile, description) => {
  try {
    // Upload image to Firebase Storage
    const imageRef = ref(storage, `portfolio/${imageFile.name}`);
    const snapshot = await uploadBytes(imageRef, imageFile);
    const imageUrl = await getDownloadURL(snapshot.ref);

    // Store metadata in Firestore
    await addDoc(collection(db, "portfolio"), {
      title,
      technologies,
      image: imageUrl,
      description,
      createdAt: new Date(),
    });

    console.log("Portfolio item added successfully!");
  } catch (error) {
    console.error("Error adding portfolio item: ", error);
  }
};

**Usage Example:**

const fileInput = document.querySelector("#fileInput");
const title = "My Portfolio Project";
const technologies = ["Vue.js", "Laravel", "Firebase"];
const description = "A great portfolio project.";

fileInput.addEventListener("change", (event) => {
  const file = event.target.files[0];
  if (file) {
    uploadPortfolioItem(title, technologies, file, description);
  }
});

### **3. Fetch All Portfolio Items**

import { collection, getDocs } from "firebase/firestore";

const fetchPortfolioItems = async () => {
  const querySnapshot = await getDocs(collection(db, "portfolio"));
  const portfolioItems = [];
  
  querySnapshot.forEach((doc) => {
    portfolioItems.push({ id: doc.id, ...doc.data() });
  });

  return portfolioItems;
};

// Usage Example
fetchPortfolioItems().then((items) => console.log(items));

### **4. Display Portfolio Items in Vue.js**
If you're using Vue.js, you can integrate the fetch function like this:

<template>
  <div>
    <h2>My Portfolio</h2>
    <div v-for="item in portfolioItems" :key="item.id">
      <h3>{{ item.title }}</h3>
      <p>{{ item.technologies.join(', ') }}</p>
      <img :src="item.image" alt="Portfolio Image" width="200">
      <p>{{ item.description }}</p>
    </div>
  </div>
</template>

<script>
import { fetchPortfolioItems } from "@/firebase"; // Adjust path accordingly

export default {
  data() {
    return {
      portfolioItems: [],
    };
  },
  async mounted() {
    this.portfolioItems = await fetchPortfolioItems();
  },
};
</script>

### **Summary**
– **Firebase Storage**: Stores images.
– **Firestore Database**: Stores metadata (title, technologies, description, image URL).
– **Vue.js Component**: Fetches and displays the portfolio.

Let me know if you need further customization!

User
Using composition api
Assistant
If you're using **Vue 3 Composition API**, here's how you can integrate Firebase Cloud Storage and Firestore to manage your portfolio items.

### **1. Set Up Firebase**
Install Firebase SDK if you haven't:

npm install firebase

Initialize Firebase in a separate file (`firebase.js`):

import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};

const app = initializeApp(firebaseConfig);
export const storage = getStorage(app);
export const db = getFirestore(app);

### **2. Upload Portfolio Item (Using Composition API)**
Create a **Firebase Composable** (`usePortfolio.js`):

import { ref as storageRef, uploadBytes, getDownloadURL } from "firebase/storage";
import { collection, addDoc, getDocs } from "firebase/firestore";
import { ref } from "vue";
import { db, storage } from "@/firebase";

export function usePortfolio() {
  const portfolioItems = ref([]);

  // Upload Portfolio Item
  const uploadPortfolioItem = async (title, technologies, imageFile, description) => {
    try {
      // Upload image to Firebase Storage
      const imgRef = storageRef(storage, `portfolio/${imageFile.name}`);
      const snapshot = await uploadBytes(imgRef, imageFile);
      const imageUrl = await getDownloadURL(snapshot.ref);

      // Store metadata in Firestore
      await addDoc(collection(db, "portfolio"), {
        title,
        technologies,
        image: imageUrl,
        description,
        createdAt: new Date(),
      });

      console.log("Portfolio item added successfully!");
    } catch (error) {
      console.error("Error adding portfolio item:", error);
    }
  };

  // Fetch Portfolio Items
  const fetchPortfolioItems = async () => {
    try {
      const querySnapshot = await getDocs(collection(db, "portfolio"));
      portfolioItems.value = querySnapshot.docs.map((doc) => ({
        id: doc.id,
        ...doc.data(),
      }));
    } catch (error) {
      console.error("Error fetching portfolio items:", error);
    }
  };

  return { portfolioItems, uploadPortfolioItem, fetchPortfolioItems };
}

### **3. Portfolio Upload Component (Composition API)**
Create `PortfolioUploader.vue`:

<template>
  <div>
    <h2>Upload Portfolio Item</h2>
    <form @submit.prevent="handleSubmit">
      <input type="text" v-model="title" placeholder="Title" required />
      <input type="text" v-model="technologies" placeholder="Technologies (comma separated)" required />
      <input type="file" @change="handleFileChange" required />
      <textarea v-model="description" placeholder="Description"></textarea>
      <button type="submit">Upload</button>
    </form>
  </div>
</template>

<script>
import { ref } from "vue";
import { usePortfolio } from "@/composables/usePortfolio";

export default {
  setup() {
    const { uploadPortfolioItem } = usePortfolio();
    const title = ref("");
    const technologies = ref("");
    const imageFile = ref(null);
    const description = ref("");

    const handleFileChange = (event) => {
      imageFile.value = event.target.files[0];
    };

    const handleSubmit = async () => {
      if (!imageFile.value) {
        alert("Please select an image.");
        return;
      }
      const techArray = technologies.value.split(",").map((tech) => tech.trim());
      await uploadPortfolioItem(title.value, techArray, imageFile.value, description.value);

      // Reset form
      title.value = "";
      technologies.value = "";
      imageFile.value = null;
      description.value = "";
    };

    return { title, technologies, imageFile, description, handleFileChange, handleSubmit };
  },
};
</script>

### **4. Portfolio List Component (Composition API)**
Create `PortfolioList.vue`:

<template>
  <div>
    <h2>Portfolio Items</h2>
    <button @click="fetchPortfolioItems">Load Portfolio</button>
    <div v-if="loading">Loading...</div>
    <div v-else>
      <div v-for="item in portfolioItems" :key="item.id">
        <h3>{{ item.title }}</h3>
        <p>Technologies: {{ item.technologies.join(', ') }}</p>
        <img :src="item.image" alt="Portfolio Image" width="200" />
        <p>{{ item.description }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import { onMounted, ref } from "vue";
import { usePortfolio } from "@/composables/usePortfolio";

export default {
  setup() {
    const { portfolioItems, fetchPortfolioItems } = usePortfolio();
    const loading = ref(true);

    onMounted(async () => {
      await fetchPortfolioItems();
      loading.value = false;
    });

    return { portfolioItems, fetchPortfolioItems, loading };
  },
};
</script>

### **5. Use Components in `App.vue`**

<template>
  <PortfolioUploader />
  <PortfolioList />
</template>

<script>
import PortfolioUploader from "@/components/PortfolioUploader.vue";
import PortfolioList from "@/components/PortfolioList.vue";

export default {
  components: {
    PortfolioUploader,
    PortfolioList,
  },
};
</script>

### **Summary**
✅ **Firebase Storage** → Stores images
✅ **Firestore** → Stores title, technologies, description, image URL
✅ **Composition API** → Manages state & logic
✅ **Reusable Composables (`usePortfolio.js`)** → Fetch & upload portfolio items
✅ **Vue Components (`PortfolioUploader.vue` & `PortfolioList.vue`)** → UI

This setup ensures a **structured and reusable** way to handle portfolio items in Vue 3 with Firebase. Let me know if you need any modifications! 🚀

Leave a Comment

Your email address will not be published. Required fields are marked *