채용공고 웹사이트: 빌딩 인덱스 페이지




GitHub: https://github.com/Sokhavuth/opine-job
데노 배치: https://khmerweb-job.deno.dev/users/post

대시보드에서 페이지를 작성하기 전에 먼저 다른 페이지가 작성될 대시보드의 기초로 사용할 인덱스 페이지 작성을 시작할 수 있습니다. 우리는 이 인덱스 페이지를 머리글, 사이드바, 바닥글과 다른 페이지를 포함하는 주요 부분으로 디자인할 수 있습니다.

React에서와 같이 Nano JSX에서 서로 다른 구성 요소를 함께 결합하려면 자식 구성 요소를 부모 구성 요소의 소품으로 전달하고 모든 구성 요소를 마지막 자식의 문자열로 렌더링해야 합니다.


// controllers/users/post.js

import post from "../../views/users/post.jsx";


class Post{
    async getPage(req, res){
        const config = req.mysetting();
        config.page_title = "Post Page";
        config.route = "/users/post";
        config.username = (await req.mysession.get("user")).title;

        const html = await post(config);
        res.send(html);
    }
}


export default new Post();



// views/users/post.jsx

/** @jsx h */
import { h, renderSSR } from "../../deps.ts";
import Index from "./index.jsx";


function PostJsx(props){
    return(
        <section class="Post">
            Post
        </section>
    )
}

export default function Post(props){
    props.pageInner = PostJsx;
    const html = renderSSR(<Index data={ props } />);

    return `<!DOCTYPE html>${ html }`;
}



// views/users/index.jsx

/** @jsx h */
import { h } from "../../deps.ts";
import Base from "../base.jsx";


function IndexJsx(props){
    const Page = props.data.pageInner;
    return(
        <section class="Index">
            <link rel="stylesheet" href="/css/users/index.css" />
            <header>
                <div class="inner region">
                    <div class="title">{props.data.page_title}</div>
                    <form action="/admin/search" method="post">
                        <select name="admin_search">
                            <option>All</option>
                            <option>Category</option>
                        </select>
                        <input type="text" name="admin_q" required placeholder="Search" />
                        <input type="submit" value="Search" />
                    </form>
                    <div class="logout"><span>{props.data.username}</span> | <a href="/">Home</a> | <a href="/logout">Logout</a></div>
                </div>
            </header>

            <div class="main region">
                <div class="sidebar">
                    <div class="inner">
                        <a href="/admin/post"><img src="/images/post.png" /></a>
                        <a href="/admin/post">Post</a>

                        <a href="/admin/category"><img src="/images/category.png" /></a>
                        <a href="/admin/category">Category</a>

                        <a href="/admin/upload"><img src="/images/upload.png" /></a>
                        <a href="/admin/upload">Upload</a>

                        <a href="/admin/user"><img src="/images/users.png" /></a>
                        <a href="/admin/user">User</a>

                        <a href="/admin/setting"><img src="/images/setting.png" /></a>
                        <a href="/admin/setting">Setting</a>
                    </div>
                </div>
                <div class="content">
                    <Page data={props.data} />
                </div>
            </div>

            <div class="footer region">
                <div class="info">Total amount of items: {props.data.count}</div>
                <ul class="list">

                </ul>
                <div class="pagination" dangerouslySetInnerHTML={{__html: `
                    <img onclick="paginate('${props.data.route}')" src="/images/load-more.png" />
                `}}/>

                <div class="credit">&copy; <a href="https://khmerweb.vercel.app/">Khmer Web 2022</a></div>
            </div>
        </section>
    )
}

export default function Index(props){
    props.data.page = IndexJsx;
    return(<Base data={ props.data } />);
}



// views/base.jsx

/** @jsx h */
import { h } from "../deps.ts";


export default function Base(props){
    const Page = props.data.page;
    return(
        <html>
            <head>
                <meta charSet="UTF-8"/>
                <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
                <title>{props.data.site_title} | {props.data.page_title}</title>
                <link href="/images/siteLogo.png" rel="icon" />
                <link href="/css/style.css" rel="stylesheet" />
                <link href="/fonts/setup.css" rel="stylesheet" />
                <script src="/js/jquery.js"></script>
            </head>
            <body>
                <Page data={props.data} />
            </body>
        </html>
    )
  }



/* static/styles/admin/index.css */

.Index header{
    background: var(--background-dark);
    border-bottom: 7px solid white;
    margin-bottom: 20px;
}

.Index header .inner{
    padding: 5px 0;
}

.Index header .inner .title{
    font: 30px/1.5 StardosStencil, Limonf3;
    color: orange;
}

.Index header .inner{
    display: grid;
    grid-template-columns: 25% auto 25%;
    align-items: center;
}

.Index header .inner form{
    display: grid;
    grid-template-columns: 20% auto 20%;
}

.Index header .inner form input,
.Index header .inner form select{
    font: var(--body-font);
    padding: 2px 5px;
}

.Index header .inner .logout{
    text-align: right;
    color: white;
}

.Index header .inner .logout a{
    color: white;
}

.Index .main{
    display: grid;
    grid-template-columns: calc(25% - 10px) 75%;
    grid-gap: 10px;
}

.Index .main .sidebar{
    background: rgb(182, 182, 182);
    padding: 20px;
}

.Index .main .sidebar .inner{
    display: grid;
    grid-template-columns: 25% auto;
    grid-gap: 20px 10px;
    align-items: center;
}

.Index .main .sidebar .inner img{
    width: 100%;
    float: left;
}

.Index .main .sidebar .inner a{
    font: 18px/1.5 StardosStencil, Bayon;
}

.Index .footer .info{
    margin-top: 10px;
    background: rgb(182, 182, 182);
    text-align: center;
    padding: 10px;
    color: rgb(88, 88, 88);;
}

.Index .footer ul{
    list-style-type: none;
    display: grid;
    grid-template-columns: calc(50% - 5px) calc(50% - 5px);
    grid-gap: 10px;
    padding: 10px 0;
}

.Index .footer ul li{
    display: grid;
    grid-template-columns: 25% 60% 15%;
    background: rgb(182, 182, 182);
    align-items: center;
}

.Index .footer ul li .thumb{
    display: block;
    position: relative;
    padding-top: 56.25%;
}

.Index .footer ul li .thumb img{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    float: left;
}

.Index .footer ul li .thumb .play-icon{
    position: absolute;
    width: 25%;
    height: auto;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
}

.Index .footer ul li .title{
    padding: 5px 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.Index .footer ul li .title a{
    font: 17px/1.5 StardosStencil, Limonf3;
}   

.Index .footer ul li .edit img{
    width: 35px;
    margin-right: 5px;
    float: left;
    visibility: hidden;
}

.Index .footer ul li:hover .edit img{
    visibility: visible;
}

.Index .footer .pagination{
    text-align: center;
    background: rgb(182, 182, 182);
    padding: 5px 0 0;
}

.Index .footer .pagination img:hover{
    cursor: pointer;
    opacity: .7;
}

.Index .footer .credit{
    text-align: center;
    padding: 30px 0;
}

좋은 웹페이지 즐겨찾기