diff --git a/src/app.js b/src/app.js index 3eb9f19..0bec917 100644 --- a/src/app.js +++ b/src/app.js @@ -97,29 +97,60 @@ app.get('/logout', (req, res) => { // ===== 루트 → 관리자로 리다이렉트 ===== app.get('/', (req, res) => res.redirect('/admin')); -// ===== 관리자 페이지 ===== -app.get('/admin', adminAuth, (req, res) => { - res.render('admin/dashboard'); +// ===== 관리자 페이지 (데이터 서버사이드 렌더링) ===== +app.get('/admin', adminAuth, async (req, res) => { + try { + const sites = await db.query(`SELECT s.*, (SELECT COUNT(*) FROM crawl_results WHERE site_id = s.id) AS crawl_count FROM sites s ORDER BY s.id`); + const adsense = await db.query('SELECT * FROM adsense_configs ORDER BY id'); + const logs = await db.query(`SELECT l.*, s.name AS site_name FROM crawl_logs l LEFT JOIN sites s ON s.id = l.site_id ORDER BY l.created_at DESC LIMIT 10`); + res.render('admin/dashboard', { + initialData: JSON.stringify({ sites: sites.rows, adsense: adsense.rows, logs: logs.rows }) + }); + } catch (e) { res.render('admin/dashboard', { initialData: '{}' }); } }); -app.get('/admin/sites', adminAuth, (req, res) => { - res.render('admin/sites'); +app.get('/admin/sites', adminAuth, async (req, res) => { + try { + const sites = await db.query(`SELECT s.*, ac.name AS adsense_name, (SELECT COUNT(*) FROM crawl_results WHERE site_id = s.id) AS crawl_count FROM sites s LEFT JOIN adsense_configs ac ON ac.id = s.adsense_config_id ORDER BY s.id`); + const adsense = await db.query('SELECT * FROM adsense_configs ORDER BY id'); + res.render('admin/sites', { + initialData: JSON.stringify({ sites: sites.rows, adsense: adsense.rows }) + }); + } catch (e) { res.render('admin/sites', { initialData: '{}' }); } }); -app.get('/admin/sites/:id', adminAuth, (req, res) => { - res.render('admin/site-detail', { siteId: req.params.id }); +app.get('/admin/sites/:id', adminAuth, async (req, res) => { + try { + const site = await db.query('SELECT * FROM sites WHERE id = $1', [req.params.id]); + const results = await db.query(`SELECT id, site_id, status, error_message, crawled_at, jsonb_array_length(COALESCE(parsed_data->'items','[]'::jsonb)) AS item_count FROM crawl_results WHERE site_id = $1 ORDER BY crawled_at DESC LIMIT 20`, [req.params.id]); + res.render('admin/site-detail', { + siteId: req.params.id, + initialData: JSON.stringify({ site: site.rows[0] || {}, results: results.rows }) + }); + } catch (e) { res.render('admin/site-detail', { siteId: req.params.id, initialData: '{}' }); } }); -app.get('/admin/adsense', adminAuth, (req, res) => { - res.render('admin/adsense'); +app.get('/admin/adsense', adminAuth, async (req, res) => { + try { + const adsense = await db.query('SELECT * FROM adsense_configs ORDER BY id'); + res.render('admin/adsense', { initialData: JSON.stringify(adsense.rows) }); + } catch (e) { res.render('admin/adsense', { initialData: '[]' }); } }); -app.get('/admin/domains', adminAuth, (req, res) => { - res.render('admin/domains'); +app.get('/admin/domains', adminAuth, async (req, res) => { + try { + const domains = await db.query(`SELECT d.*, s.name AS site_name FROM domain_mappings d LEFT JOIN sites s ON s.id = d.site_id ORDER BY d.id`); + const sites = await db.query('SELECT id, name FROM sites ORDER BY id'); + const adsense = await db.query('SELECT id, name FROM adsense_configs ORDER BY id'); + res.render('admin/domains', { initialData: JSON.stringify({ domains: domains.rows, sites: sites.rows, adsense: adsense.rows }) }); + } catch (e) { res.render('admin/domains', { initialData: '{}' }); } }); -app.get('/admin/logs', adminAuth, (req, res) => { - res.render('admin/logs'); +app.get('/admin/logs', adminAuth, async (req, res) => { + try { + const logs = await db.query(`SELECT l.*, s.name AS site_name FROM crawl_logs l LEFT JOIN sites s ON s.id = l.site_id ORDER BY l.created_at DESC LIMIT 100`); + res.render('admin/logs', { initialData: JSON.stringify(logs.rows) }); + } catch (e) { res.render('admin/logs', { initialData: '[]' }); } }); // ===== API ===== diff --git a/views/admin/adsense.ejs b/views/admin/adsense.ejs index 7c9e782..593f5da 100644 --- a/views/admin/adsense.ejs +++ b/views/admin/adsense.ejs @@ -15,28 +15,13 @@
- 도메인을 특정 사이트에 연결하면, 해당 도메인으로 접속 시 크롤링 결과가 자동으로 표시됩니다.
- 슬러그 기반 접근도 가능합니다: /s/{slug}
+ 도메인을 특정 사이트에 연결하면, 해당 도메인으로 접속 시 크롤링 결과가 자동으로 표시됩니다.
| 도메인 | 연결 사이트 | 상태 | 등록일 | 액션 |
|---|