tpp menulis

 <!doctype html>

<html lang="id">

<head>

  <meta charset="utf-8" />

  <meta name="viewport" content="width=device-width,initial-scale=1" />

  <title>Citizen Journalism Portal</title>

  <style>

    body { font-family: system-ui, sans-serif; background: #081020; color: #e6eef6; margin: 0; padding: 24px; }

    h1, h2 { color: #60a5fa; }

    .container { max-width: 960px; margin: auto; }

    .btn { background: #2563eb; color: white; border: none; padding: 8px 14px; border-radius: 6px; cursor: pointer; }

    .btn:disabled { opacity: 0.5; cursor: not-allowed; }

    input, textarea { width: 100%; padding: 8px; margin: 6px 0; border-radius: 6px; border: 1px solid #334155; background: #0f172a; color: #e6eef6; }

    .grid { display: grid; gap: 12px; }

    .author-card { display: flex; align-items: center; gap: 12px; background: rgba(255,255,255,0.05); border-radius: 12px; padding: 12px; }

    .author-photo { width: 60px; height: 60px; border-radius: 50%; object-fit: cover; }

    .author-info { flex: 1; }

    .rank { font-weight: bold; color: #38bdf8; font-size: 20px; width: 32px; text-align: center; }

    .form-section { background: rgba(255,255,255,0.05); padding: 16px; border-radius: 12px; margin-top: 24px; }

  </style>

</head>

<body>

  <div class="container">

    <h1>📢 Portal Citizen Journalism</h1>

    <div id="auth-section" class="grid">

      <h2>Masuk / Daftar</h2>

      <input id="email" type="email" placeholder="Email" />

      <input id="password" type="password" placeholder="Password" />

      <button id="signup-btn" class="btn">Daftar</button>

      <button id="signin-btn" class="btn">Masuk</button>

      <button id="google-btn" class="btn">Masuk dengan Google</button>

      <button id="reset-btn" class="btn">Lupa Password</button>

    </div>


    <div id="dashboard" style="display:none">

      <h2>Selamat datang, <span id="user-name"></span>!</h2>

      <button id="logout-btn" class="btn">Keluar</button>

      <hr>


      <h2>🏆 Peringkat Penulis</h2>

      <div id="leaderboard" class="grid"></div>


      <div class="form-section">

        <h2>🧑‍🎨 Profil Saya</h2>

        <form id="profile-form">

          <label>Nama Lengkap</label>

          <input type="text" id="profile-name" required />

          <label>Bio Singkat</label>

          <textarea id="profile-bio" required></textarea>


          <label>Instagram</label>

          <input type="url" id="profile-ig" placeholder="https://instagram.com/..." />

          <label>Facebook</label>

          <input type="url" id="profile-fb" placeholder="https://facebook.com/..." />

          <label>YouTube</label>

          <input type="url" id="profile-yt" placeholder="https://youtube.com/@..." />

          <label>X (Twitter)</label>

          <input type="url" id="profile-x" placeholder="https://x.com/..." />


          <label>Foto Profil</label>

          <input type="file" id="profile-photo" accept="image/png,image/jpeg,image/jpg" required />

          <small>📸 Maksimum ukuran 2 MB (format: JPG, JPEG, PNG)</small>

          <img id="photo-preview" src="" alt="Preview" style="display:none; margin-top:10px; width:100px; height:100px; border-radius:50%; object-fit:cover;">


          <button type="submit" id="save-profile" class="btn" disabled>Simpan Profil</button>

        </form>

      </div>

    </div>

  </div>


  <script type="module">

    import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-app.js";

    import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, GoogleAuthProvider, signInWithPopup, sendPasswordResetEmail, signOut, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-auth.js";

    import { getFirestore, doc, setDoc, getDoc, collection, getDocs } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-firestore.js";

    import { getStorage, ref, uploadBytes, getDownloadURL } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-storage.js";


    const firebaseConfig = {

      apiKey: "API_KEY_KAMU",

      authDomain: "PROJECT_ID.firebaseapp.com",

      projectId: "PROJECT_ID",

      storageBucket: "PROJECT_ID.appspot.com",

      messagingSenderId: "SENDER_ID",

      appId: "APP_ID"

    };


    const app = initializeApp(firebaseConfig);

    const auth = getAuth(app);

    const db = getFirestore(app);

    const storage = getStorage(app);


    const emailEl = document.getElementById('email');

    const passEl = document.getElementById('password');


    const authSection = document.getElementById('auth-section');

    const dashboard = document.getElementById('dashboard');

    const userNameEl = document.getElementById('user-name');

    const leaderboardEl = document.getElementById('leaderboard');


    document.getElementById('signup-btn').onclick = async () => {

      const email = emailEl.value;

      const pass = passEl.value;

      await createUserWithEmailAndPassword(auth, email, pass);

    };


    document.getElementById('signin-btn').onclick = async () => {

      const email = emailEl.value;

      const pass = passEl.value;

      await signInWithEmailAndPassword(auth, email, pass);

    };


    document.getElementById('google-btn').onclick = async () => {

      const provider = new GoogleAuthProvider();

      await signInWithPopup(auth, provider);

    };


    document.getElementById('reset-btn').onclick = async () => {

      const email = emailEl.value;

      await sendPasswordResetEmail(auth, email);

      alert('Link reset password dikirim ke email.');

    };


    document.getElementById('logout-btn').onclick = () => signOut(auth);


    onAuthStateChanged(auth, async (user) => {

      if (user) {

        authSection.style.display = 'none';

        dashboard.style.display = 'block';

        userNameEl.textContent = user.email;

        loadAuthors();

        loadProfile(user.uid);

      } else {

        authSection.style.display = 'grid';

        dashboard.style.display = 'none';

      }

    });


    function hitungSkor(a){ return (a.artikel||0)*10 + (a.unduhan||0)/10 + (a.rating||0)*20; }


    async function loadAuthors(){

      const snapshot = await getDocs(collection(db, 'authors'));

      const authors = snapshot.docs.map(d => d.data());

      authors.sort((a,b)=>hitungSkor(b)-hitungSkor(a));

      leaderboardEl.innerHTML = authors.map((a,i)=>`

        <div class="author-card">

          <div class="rank">#${i+1}</div>

          <img src="${a.foto || 'https://via.placeholder.com/60'}" class="author-photo">

          <div class="author-info">

            <div><strong>${a.nama}</strong></div>

            <div>${a.bio||''}</div>

          </div>

        </div>

      `).join('');

    }


    const profileForm = document.getElementById('profile-form');

    const saveBtn = document.getElementById('save-profile');

    const photoInput = document.getElementById('profile-photo');

    const photoPreview = document.getElementById('photo-preview');


    let uploadedPhotoURL = '';


    photoInput.addEventListener('change', async (e) => {

      const file = e.target.files[0];

      if (!file) return;


      const validTypes = ['image/jpeg', 'image/png', 'image/jpg'];

      if (!validTypes.includes(file.type)) {

        alert('Hanya file JPG, JPEG, atau PNG yang diperbolehkan.');

        e.target.value = '';

        saveBtn.disabled = true;

        return;

      }


      if (file.size > 2 * 1024 * 1024) {

        alert('Ukuran file maksimal 2 MB.');

        e.target.value = '';

        saveBtn.disabled = true;

        return;

      }


      const user = auth.currentUser;

      const storageRef = ref(storage, `avatars/${user.uid}.jpg`);

      await uploadBytes(storageRef, file);

      uploadedPhotoURL = await getDownloadURL(storageRef);

      photoPreview.src = uploadedPhotoURL;

      photoPreview.style.display = 'block';

      saveBtn.disabled = false;

    });


    async function loadProfile(uid){

      const docRef = doc(db, 'authors', uid);

      const docSnap = await getDoc(docRef);

      if (docSnap.exists()){

        const d = docSnap.data();

        document.getElementById('profile-name').value = d.nama || '';

        document.getElementById('profile-bio').value = d.bio || '';

        document.getElementById('profile-ig').value = d.sosial?.instagram || '';

        document.getElementById('profile-fb').value = d.sosial?.facebook || '';

        document.getElementById('profile-yt').value = d.sosial?.youtube || '';

        document.getElementById('profile-x').value = d.sosial?.x || '';

        if (d.foto){

          photoPreview.src = d.foto;

          photoPreview.style.display = 'block';

          uploadedPhotoURL = d.foto;

          saveBtn.disabled = false;

        }

      }

    }


    profileForm.addEventListener('submit', async (e) => {

      e.preventDefault();

      if (!uploadedPhotoURL){ alert('Silakan upload foto profil terlebih dahulu.'); return; }

      const user = auth.currentUser;

      const data = {

        nama: document.getElementById('profile-name').value,

        bio: document.getElementById('profile-bio').value,

        foto: uploadedPhotoURL,

        sosial: {

          instagram: document.getElementById('profile-ig').value,

          facebook: document.getElementById('profile-fb').value,

          youtube: document.getElementById('profile-yt').value,

          x: document.getElementById('profile-x').value

        }

      };

      await setDoc(doc(db, 'authors', user.uid), data, { merge: true });

      alert('Profil berhasil disimpan!');

      loadAuthors();

    });

  </script>

</body>

</html>


Post a Comment

Previous Post Next Post