import React, { useState, useRef } from "react";


// PaperSubmissionApp.jsx

// Single-file React component (default export) using Tailwind CSS for styling.

// - Registration & Login (local state mock)

// - Abstract & Cover Letter inputs

// - Manuscript file upload (single file)

// - Figures upload (multiple files) with image previews

// - Basic client-side validation and friendly UI

// Notes:

// - This component is front-end only. Replace the `handleSubmit*` functions

//   with real API calls (e.g. fetch/axios) to integrate with your backend.

// - Tailwind should be available in the host project.

// - shadcn/ui components can be swapped in for improved visuals.


export default function PaperSubmissionApp() {

  const [view, setView] = useState("home"); // home | register | login | submit


  // --- Auth state (mock) ---

  const [user, setUser] = useState(null);

  const [registerData, setRegisterData] = useState({ name: "", email: "", password: "", confirm: "" });

  const [loginData, setLoginData] = useState({ email: "", password: "" });

  const [authErrors, setAuthErrors] = useState("");


  // --- Submission state ---

  const [title, setTitle] = useState("");

  const [abstract, setAbstract] = useState("");

  const [coverLetter, setCoverLetter] = useState("");

  const [manuscriptFile, setManuscriptFile] = useState(null);

  const [figureFiles, setFigureFiles] = useState([]);

  const [figPreviews, setFigPreviews] = useState([]);

  const [submitMessage, setSubmitMessage] = useState("");


  const fileInputRef = useRef(null);

  const figInputRef = useRef(null);


  // --- Helpers ---

  function validateRegister() {

    const { name, email, password, confirm } = registerData;

    if (!name || !email || !password) return "All fields are required.";

    if (password.length < 6) return "Password must be at least 6 characters.";

    if (password !== confirm) return "Passwords do not match.";

    return "";

  }


  function handleRegister(e) {

    e.preventDefault();

    const err = validateRegister();

    if (err) return setAuthErrors(err);

    // Mock register -> set user locally

    setUser({ name: registerData.name, email: registerData.email });

    setAuthErrors("");

    setView("submit");

  }


  function handleLogin(e) {

    e.preventDefault();

    // Mock login: accept any non-empty email/password

    if (!loginData.email || !loginData.password) return setAuthErrors("Provide email and password.");

    setUser({ name: loginData.email.split("@")[0], email: loginData.email });

    setAuthErrors("");

    setView("submit");

  }


  function handleLogout() {

    setUser(null);

    setView("home");

  }


  // Manuscript upload (single file)

  function handleManuscriptChange(e) {

    const f = e.target.files && e.target.files[0];

    setManuscriptFile(f || null);

  }


  // Figures: multiple + previews

  function handleFiguresChange(e) {

    const files = Array.from(e.target.files || []);

    setFigureFiles(files);


    // build previews for images (non-images will be shown with generic icon)

    const previews = files.map((f) => {

      const isImg = f.type.startsWith("image/");

      if (!isImg) return { name: f.name, url: null, size: f.size };

      return { name: f.name, url: URL.createObjectURL(f), size: f.size };

    });

    // revoke previous previews to avoid memory leak

    figPreviews.forEach((p) => p.url && URL.revokeObjectURL(p.url));

    setFigPreviews(previews);

  }


  function removeFigure(index) {

    const files = [...figureFiles];

    files.splice(index, 1);

    setFigureFiles(files);

    const previews = [...figPreviews];

    const removed = previews.splice(index, 1)[0];

    if (removed && removed.url) URL.revokeObjectURL(removed.url);

    setFigPreviews(previews);


    // also reset the file input so user can re-add

    if (figInputRef.current) figInputRef.current.value = "";

  }


  // Basic client-side submission (pack into FormData and print to console)

  async function handleSubmitManuscript(e) {

    e.preventDefault();

    if (!user) return setSubmitMessage("You must be logged in to submit.");

    if (!title.trim()) return setSubmitMessage("Please provide a manuscript title.");

    if (!abstract.trim()) return setSubmitMessage("Please provide an abstract.");

    if (!manuscriptFile) return setSubmitMessage("Please upload the manuscript file (PDF, DOCX, etc.).");


    setSubmitMessage("Preparing submission...");


    // Build FormData -- replace with API endpoint

    const fd = new FormData();

    fd.append("title", title);

    fd.append("abstract", abstract);

    fd.append("coverLetter", coverLetter);

    fd.append("manuscript", manuscriptFile);

    figureFiles.forEach((f, i) => fd.append(`figure_${i + 1}`, f));

    fd.append("submittedBy", user.email);


    // Demo: create a JSON-friendly summary and log it

    const summary = {

      title,

      abstract: abstract.slice(0, 300) + (abstract.length > 300 ? "..." : ""),

      coverLetter: coverLetter.slice(0, 300) + (coverLetter.length > 300 ? "..." : ""),

      manuscriptFile: manuscriptFile ? { name: manuscriptFile.name, size: manuscriptFile.size } : null,

      figures: figureFiles.map((f) => ({ name: f.name, size: f.size })),

      submittedBy: user.email,

      submittedAt: new Date().toISOString(),

    };


    // Simulate upload delay

    await new Promise((res) => setTimeout(res, 800));

    console.log("FormData (simulated):", summary);


    setSubmitMessage("Submission prepared (see console). Replace handleSubmitManuscript with a real API call to POST FormData.");

  }


  // --- UI pieces ---

  const Nav = () => (

    <header className="bg-white shadow-sm border-b">

      <div className="max-w-4xl mx-auto px-4 py-3 flex items-center justify-between">

        <div className="flex items-center gap-3">

          <div className="text-2xl font-extrabold">PaperPortal</div>

          <div className="text-sm text-slate-500">Submit and manage your manuscript</div>

        </div>

        <nav className="flex items-center gap-3">

          {!user ? (

            <>

              <button onClick={() => setView("register")} className="btn">Register</button>

              <button onClick={() => setView("login")} className="btn-outline">Login</button>

            </>

          ) : (

            <>

              <div className="text-sm">Signed in as <strong>{user.name}</strong></div>

              <button onClick={() => setView("submit")} className="btn">Submit</button>

              <button onClick={handleLogout} className="btn-ghost">Logout</button>

            </>

          )}

        </nav>

      </div>

    </header>

  );


  function Home() {

    return (

      <div className="max-w-4xl mx-auto p-6">

        <h1 className="text-3xl font-bold mb-2">Welcome to PaperPortal</h1>

        <p className="text-slate-600 mb-6">A minimal submission front-end: register/login, write an abstract & cover letter, upload manuscript and figures.</p>


        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">

          <Card title="1. Register" body="Create an account so you can submit and track your manuscript." action={() => setView("register")} />

          <Card title="2. Login" body="Sign in to continue to submission." action={() => setView("login")} />

          <Card title="3. Submit" body="Start a new submission (requires login)." action={() => setView(user ? "submit" : "login")} />

        </div>

      </div>

    );

  }


  function Card({ title, body, action }) {

    return (

      <div className="border rounded-2xl p-4 shadow-sm">

        <h3 className="font-semibold mb-2">{title}</h3>

        <p className="text-sm text-slate-600 mb-4">{body}</p>

        <button onClick={action} className="px-3 py-2 rounded-md bg-slate-800 text-white text-sm">Open</button>

      </div>

    );

  }


  function RegisterView() {

    return (

      <div className="max-w-2xl mx-auto p-6">

        <h2 className="text-2xl font-bold mb-4">Register</h2>

        {authErrors && <div className="mb-3 text-red-600">{authErrors}</div>}

        <form onSubmit={handleRegister} className="space-y-3">

          <div>

            <label className="block text-sm mb-1">Full name</label>

            <input value={registerData.name} onChange={(e) => setRegisterData({ ...registerData, name: e.target.value })} className="input" />

          </div>

          <div>

            <label className="block text-sm mb-1">Email</label>

            <input value={registerData.email} onChange={(e) => setRegisterData({ ...registerData, email: e.target.value })} className="input" type="email" />

          </div>

          <div className="grid grid-cols-2 gap-3">

            <div>

              <label className="block text-sm mb-1">Password</label>

              <input value={registerData.password} onChange={(e) => setRegisterData({ ...registerData, password: e.target.value })} className="input" type="password" />

            </div>

            <div>

              <label className="block text-sm mb-1">Confirm</label>

              <input value={registerData.confirm} onChange={(e) => setRegisterData({ ...registerData, confirm: e.target.value })} className="input" type="password" />

            </div>

          </div>

          <div className="flex gap-3">

            <button type="submit" className="btn">Create account</button>

            <button type="button" className="btn-ghost" onClick={() => setView("home")}>Back</button>

          </div>

        </form>

      </div>

    );

  }


  function LoginView() {

    return (

      <div className="max-w-2xl mx-auto p-6">

        <h2 className="text-2xl font-bold mb-4">Login</h2>

        {authErrors && <div className="mb-3 text-red-600">{authErrors}</div>}

        <form onSubmit={handleLogin} className="space-y-3">

          <div>

            <label className="block text-sm mb-1">Email</label>

            <input value={loginData.email} onChange={(e) => setLoginData({ ...loginData, email: e.target.value })} className="input" type="email" />

          </div>

          <div>

            <label className="block text-sm mb-1">Password</label>

            <input value={loginData.password} onChange={(e) => setLoginData({ ...loginData, password: e.target.value })} className="input" type="password" />

          </div>

          <div className="flex gap-3">

            <button type="submit" className="btn">Sign in</button>

            <button type="button" className="btn-ghost" onClick={() => setView("home")}>Back</button>

          </div>

        </form>

      </div>

    );

  }


  function SubmitView() {

    return (

      <div className="max-w-4xl mx-auto p-6">

        <h2 className="text-2xl font-bold mb-4">New Submission</h2>

        <form onSubmit={handleSubmitManuscript} className="space-y-4">

          <div>

            <label className="block text-sm mb-1">Manuscript Title</label>

            <input value={title} onChange={(e) => setTitle(e.target.value)} className="input" placeholder="Short, descriptive title" />

          </div>


          <div>

            <label className="block text-sm mb-1">Abstract</label>

            <textarea value={abstract} onChange={(e) => setAbstract(e.target.value)} className="textarea h-32" placeholder="Paste the paper abstract here." />

            <div className="text-xs text-slate-500 mt-1">{abstract.length} characters</div>

          </div>


          <div>

            <label className="block text-sm mb-1">Cover letter (optional)</label>

            <textarea value={coverLetter} onChange={(e) => setCoverLetter(e.target.value)} className="textarea h-28" placeholder="Optional: a short cover letter to the editor" />

          </div>


          <div>

            <label className="block text-sm mb-1">Manuscript file</label>

            <input ref={fileInputRef} type="file" accept=".pdf,.doc,.docx,.tex" onChange={handleManuscriptChange} />

            {manuscriptFile && <div className="mt-2 text-sm">Selected: <strong>{manuscriptFile.name}</strong> ({Math.round(manuscriptFile.size/1024)} KB)</div>}

          </div>


          <div>

            <label className="block text-sm mb-1">Figures (multiple)</label>

            <input ref={figInputRef} type="file" accept="image/*,application/pdf" onChange={handleFiguresChange} multiple />

            <div className="mt-2 grid grid-cols-2 md:grid-cols-4 gap-3">

              {figPreviews.length === 0 && <div className="text-sm text-slate-500">No figures added</div>}

              {figPreviews.map((p, i) => (

                <div key={i} className="border rounded p-2 flex flex-col items-center text-center">

                  {p.url ? (

                    <img src={p.url} className="w-full h-28 object-contain mb-2" alt={p.name} />

                  ) : (

                    <div className="w-full h-28 flex items-center justify-center text-xs text-slate-600 border rounded mb-2">{p.name}</div>

                  )}

                  <div className="text-xs">{p.name}</div>

                  <div className="flex gap-2 mt-2">

                    <button type="button" onClick={() => removeFigure(i)} className="text-xs btn-ghost">Remove</button>

                  </div>

                </div>

              ))}

            </div>

          </div>


          <div className="flex items-center gap-3">

            <button type="submit" className="btn">Submit manuscript</button>

            <button type="button" className="btn-ghost" onClick={() => { setTitle(""); setAbstract(""); setCoverLetter(""); setManuscriptFile(null); setFigureFiles([]); setFigPreviews([]); if (fileInputRef.current) fileInputRef.current.value = ""; if (figInputRef.current) figInputRef.current.value = ""; }}>Reset</button>

            <div className="text-sm text-slate-600">{submitMessage}</div>

          </div>

        </form>

      </div>

    );

  }


  return (

    <div className="min-h-screen bg-slate-50 text-slate-900">

      <Nav />

      <main className="py-8">

        {view === "home" && <Home />}

        {view === "register" && <RegisterView />}

        {view === "login" && <LoginView />}

        {view === "submit" && <SubmitView />}

      </main>


      <footer className="border-t mt-12 bg-white">

        <div className="max-w-4xl mx-auto px-4 py-6 text-sm text-slate-600">Built with ♥ — replace demo submit handler with your API endpoint to accept real submissions.</div>

      </footer>


      {/* Tiny utility styles (could be moved to global stylesheet) */}

      <style>{`

        .input { width: 100%; padding: 0.6rem; border: 1px solid #E6E7EB; border-radius: 0.5rem; }

        .textarea { width: 100%; padding: 0.6rem; border: 1px solid #E6E7EB; border-radius: 0.5rem; }

        .btn { padding: 0.5rem 0.9rem; background: #0f172a; color: white; border-radius: 0.5rem; }

        .btn-ghost { padding: 0.45rem 0.8rem; background: transparent; border-radius: 0.5rem; border: 1px solid transparent; }

        .btn-outline { padding: 0.45rem 0.8rem; background: white; border-radius: 0.5rem; border: 1px solid #CBD5E1; }

        .btn-ghost:hover, .btn:hover { opacity: 0.95; }

      `}</style>

    </div>

  );

}

Untitled page