/**
* Valley Trader Classified Ad System (Mobile Optimized)
* Single-Page Deployable Version
*/
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const nodemailer = require('nodemailer');
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir);
// Multer for image uploads
const storage = multer.diskStorage({
destination: (_, __, cb) => cb(null, 'uploads/'),
filename: (_, file, cb) => cb(null, Date.now() + '-' + file.originalname)
});
const upload = multer({ storage });
// Email setup (Gmail example)
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_USER || 'YOUR_GMAIL@gmail.com',
pass: process.env.EMAIL_PASS || 'YOUR_APP_PASSWORD'
}
});
// Ads data helpers
const adsFile = path.join(__dirname, 'ads.json');
function loadAds() { return fs.existsSync(adsFile) ? JSON.parse(fs.readFileSync(adsFile)) : []; }
function saveAds(ads) { fs.writeFileSync(adsFile, JSON.stringify(ads, null, 2)); }
// Serve single HTML interface
app.get('/', (_, res) => res.send(`
The Valley Trader Classifieds
The Valley Trader Classifieds
๐งพ Admin Dashboard
| Date | Title | Description |
Issues | Price | Photo | Status |
`));
// --- API Endpoints ---
app.post('/submit-ad', upload.single('photo'), async (req, res) => {
try {
const { title, description, issues, totalPrice } = req.body;
const photo = req.file ? req.file.filename : '';
const ads = loadAds();
const ad = { title, description, issues, totalPrice, photo, paid:false, date:new Date() };
ads.push(ad);
saveAds(ads);
await transporter.sendMail({
from: process.env.EMAIL_USER,
to: 'thevalleytrader@yahoo.com',
subject: 'New Classified Ad Submitted',
html: \`New Ad
Title: \${title}
Description: \${description}
Issues: \${issues}
Total: $\${totalPrice}
\`
});
res.json({ success:true });
} catch (e) {
console.error(e);
res.json({ success:false });
}
});
app.get('/admin/ads', (_, res) => res.json(loadAds()));
app.post('/admin/mark-paid', (req, res) => {
const { index } = req.body;
const ads=loadAds();
if(ads[index]){ads[index].paid=true;saveAds(ads);}
res.json({ success:true });
});
app.listen(PORT,()=>console.log('โ
Valley Trader app running on http://localhost:'+PORT));