add 3 demo calendar
This commit is contained in:
parent
da46b61ad7
commit
466ecf5981
20 changed files with 765 additions and 33 deletions
5
.github/workflows/release.yaml
vendored
5
.github/workflows/release.yaml
vendored
|
|
@ -16,7 +16,7 @@ env:
|
||||||
REGISTRY: docker.frappet.com
|
REGISTRY: docker.frappet.com
|
||||||
IMAGE_NAME: demo/qualifying-exam-cms
|
IMAGE_NAME: demo/qualifying-exam-cms
|
||||||
jobs:
|
jobs:
|
||||||
# act workflow_dispatch -W .github/workflows/release.yaml --input IMAGE_VER=v0.2.1-dev -s DOCKER_USER=sorawit -s DOCKER_PASS=P@ssword -s SSH_PASSWORD=P@ssw0rd
|
# act workflow_dispatch -W .github/workflows/release.yaml --input IMAGE_VER=v0.2.3-dev -s DOCKER_USER=sorawit -s DOCKER_PASS=P@ssword -s SSH_PASSWORD=P@ssw0rd
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -37,7 +37,8 @@ jobs:
|
||||||
echo "{\"version\":\"$IMAGE_VER\", \"builddate\":\"$(date +"%Y-%m-%d_%T")\",\"ref_name\":\"$GITHUB_REF\" }" > ./cms/src/lib/ver.json
|
echo "{\"version\":\"$IMAGE_VER\", \"builddate\":\"$(date +"%Y-%m-%d_%T")\",\"ref_name\":\"$GITHUB_REF\" }" > ./cms/src/lib/ver.json
|
||||||
cat ./cms/src/lib/ver.json
|
cat ./cms/src/lib/ver.json
|
||||||
echo '::set-output name=image_ver::'$IMAGE_VER
|
echo '::set-output name=image_ver::'$IMAGE_VER
|
||||||
# - name: Test Version
|
# - name: Debug act
|
||||||
|
# if: ${{ env.ACT }}
|
||||||
# run: |
|
# run: |
|
||||||
# echo $GITHUB_REF
|
# echo $GITHUB_REF
|
||||||
# echo ${{ steps.gen_ver.outputs.image_ver }}
|
# echo ${{ steps.gen_ver.outputs.image_ver }}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"push":{
|
|
||||||
|
|
||||||
},
|
|
||||||
"pull_request": {
|
|
||||||
"head": {
|
|
||||||
"ref": "sample-head-ref"
|
|
||||||
},
|
|
||||||
"base": {
|
|
||||||
"ref": "sample-base-ref"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
version: "3.4"
|
version: "3.4"
|
||||||
services:
|
services:
|
||||||
hi:
|
qualifying-exam-cms:
|
||||||
image: docker.frappet.com/demo/qualifying-exam-cms:latest
|
image: docker.frappet.com/demo/qualifying-exam-cms:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "4010:80"
|
- "4010:80"
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Bangkok
|
TZ: Asia/Bangkok
|
||||||
46
cms/package-lock.json
generated
46
cms/package-lock.json
generated
|
|
@ -18,6 +18,7 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"autoprefixer": "^10.4.7",
|
"autoprefixer": "^10.4.7",
|
||||||
|
"dayjs": "^1.11.7",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.28.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-svelte3": "^4.0.0",
|
"eslint-plugin-svelte3": "^4.0.0",
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
"prettier-plugin-svelte": "^2.8.1",
|
"prettier-plugin-svelte": "^2.8.1",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"svelte": "^3.54.0",
|
"svelte": "^3.54.0",
|
||||||
|
"svelte-calendar": "^3.1.6",
|
||||||
"svelte-check": "^3.0.1",
|
"svelte-check": "^3.0.1",
|
||||||
"svelte-preprocess": "^4.10.7",
|
"svelte-preprocess": "^4.10.7",
|
||||||
"svelte-seo": "^1.5.3",
|
"svelte-seo": "^1.5.3",
|
||||||
|
|
@ -1553,6 +1555,12 @@
|
||||||
"postcss": "^8.1.6"
|
"postcss": "^8.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dayjs": {
|
||||||
|
"version": "1.11.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
|
||||||
|
"integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
|
@ -2514,6 +2522,12 @@
|
||||||
"npm": ">=6"
|
"npm": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/just-throttle": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-throttle/-/just-throttle-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-0H4miIAWZYpnpg7oD/Y/PBb77ISSHAETif5xK9EnwIgYCO6oC8ErkJxDumMUTR44shSOwptRIArRuvNuvN/hOw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/jwa": {
|
"node_modules/jwa": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
|
@ -3563,6 +3577,16 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-calendar": {
|
||||||
|
"version": "3.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-calendar/-/svelte-calendar-3.1.6.tgz",
|
||||||
|
"integrity": "sha512-jOHiPlxBAa1LGVFQZoczdAGnCSI2RKcuQQHj32TjLbXO/P2Povx4JphPEcP7XjKj/s/jimBC6xQyFhyjD0vxbg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"dayjs": "^1.10.6",
|
||||||
|
"just-throttle": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte-check": {
|
"node_modules/svelte-check": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.1.0.tgz",
|
||||||
|
|
@ -5160,6 +5184,12 @@
|
||||||
"tailwindcss": "^3"
|
"tailwindcss": "^3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dayjs": {
|
||||||
|
"version": "1.11.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
|
||||||
|
"integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
|
@ -5882,6 +5912,12 @@
|
||||||
"semver": "^7.3.8"
|
"semver": "^7.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"just-throttle": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-throttle/-/just-throttle-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-0H4miIAWZYpnpg7oD/Y/PBb77ISSHAETif5xK9EnwIgYCO6oC8ErkJxDumMUTR44shSOwptRIArRuvNuvN/hOw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"jwa": {
|
"jwa": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
|
@ -6575,6 +6611,16 @@
|
||||||
"integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==",
|
"integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"svelte-calendar": {
|
||||||
|
"version": "3.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-calendar/-/svelte-calendar-3.1.6.tgz",
|
||||||
|
"integrity": "sha512-jOHiPlxBAa1LGVFQZoczdAGnCSI2RKcuQQHj32TjLbXO/P2Povx4JphPEcP7XjKj/s/jimBC6xQyFhyjD0vxbg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"dayjs": "^1.10.6",
|
||||||
|
"just-throttle": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"svelte-check": {
|
"svelte-check": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"autoprefixer": "^10.4.7",
|
"autoprefixer": "^10.4.7",
|
||||||
|
"dayjs": "^1.11.7",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.28.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-svelte3": "^4.0.0",
|
"eslint-plugin-svelte3": "^4.0.0",
|
||||||
|
|
@ -31,6 +32,7 @@
|
||||||
"prettier-plugin-svelte": "^2.8.1",
|
"prettier-plugin-svelte": "^2.8.1",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"svelte": "^3.54.0",
|
"svelte": "^3.54.0",
|
||||||
|
"svelte-calendar": "^3.1.6",
|
||||||
"svelte-check": "^3.0.1",
|
"svelte-check": "^3.0.1",
|
||||||
"svelte-preprocess": "^4.10.7",
|
"svelte-preprocess": "^4.10.7",
|
||||||
"svelte-seo": "^1.5.3",
|
"svelte-seo": "^1.5.3",
|
||||||
|
|
|
||||||
131
cms/src/lib/components/Calendar/Calendar.svelte
Normal file
131
cms/src/lib/components/Calendar/Calendar.svelte
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import {createEventDispatcher, onMount} from 'svelte'
|
||||||
|
let dispatch = createEventDispatcher();
|
||||||
|
import calendarize from './calendarize'
|
||||||
|
import Arrow from './CalendarArrow.svelte';
|
||||||
|
export let year = 2023;
|
||||||
|
export let month = 0; // Jan
|
||||||
|
export let offset = 0; // Sun
|
||||||
|
export let locale = "en" as (keyof typeof text_labels)|(keyof typeof text_months);
|
||||||
|
export let buddhist = false
|
||||||
|
const text_labels = {
|
||||||
|
en: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
|
||||||
|
th: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'],
|
||||||
|
}
|
||||||
|
const text_months = {
|
||||||
|
en: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||||
|
th: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
|
||||||
|
}
|
||||||
|
const today = new Date
|
||||||
|
const labels = (locale in text_labels)? text_labels[locale]:text_labels.en
|
||||||
|
const months = (locale in text_months)? text_months[locale]:text_months.en
|
||||||
|
$: today_month = today.getMonth();
|
||||||
|
$: today_year = today.getFullYear();
|
||||||
|
$: today_day = today.getDate();
|
||||||
|
|
||||||
|
let prev = calendarize(new Date(year, month-1), offset);
|
||||||
|
let current = calendarize(new Date(year, month), offset);
|
||||||
|
let next = calendarize(new Date(year, month+1), offset);
|
||||||
|
|
||||||
|
function toPrev() {
|
||||||
|
[current, next] = [prev, current];
|
||||||
|
|
||||||
|
if (--month < 0) {
|
||||||
|
month = 11;
|
||||||
|
year--;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = calendarize(new Date(year, month-1), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toNext() {
|
||||||
|
[prev, current] = [current, next];
|
||||||
|
|
||||||
|
if (++month > 11) {
|
||||||
|
month = 0;
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
next = calendarize(new Date(year, month+1), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isToday(day:number ) {
|
||||||
|
return today && today_year === year && today_month === month && today_day === day;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<Arrow left on:click={toPrev} />
|
||||||
|
<h4>{months[month]} - {year+ (buddhist?543:0)}</h4>
|
||||||
|
<Arrow on:click={toNext} />
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="month">
|
||||||
|
{#each labels as txt, idx (txt)}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<span class="label" on:click={()=>dispatch('headerClick',txt)} >{ labels[(idx + offset) % 7] }</span>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#each { length:6 } as w,idxw (idxw)}
|
||||||
|
{#if current[idxw]}
|
||||||
|
{#each { length:7 } as d,idxd (idxd)}
|
||||||
|
{#if current[idxw][idxd] != 0}
|
||||||
|
<span class="date" class:today={isToday(current[idxw][idxd])}>
|
||||||
|
{ current[idxw][idxd] }
|
||||||
|
</span>
|
||||||
|
{:else if (idxw < 1)}
|
||||||
|
<span class="date other">{ prev[prev.length - 1][idxd] }</span>
|
||||||
|
{:else}
|
||||||
|
<span class="date other">{ next[0][idxd] }</span>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
margin: 2rem auto;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 140%;
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
.month {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
text-align: right;
|
||||||
|
grid-gap: 4px;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
font-weight: 300;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
height: 50px;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
border: 1px solid #e6e4e4;
|
||||||
|
padding-right: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
.date.today {
|
||||||
|
color: #5286fa;
|
||||||
|
background: #c4d9fd;
|
||||||
|
border-color: currentColor;
|
||||||
|
}
|
||||||
|
.date.other {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
22
cms/src/lib/components/Calendar/CalendarArrow.svelte
Normal file
22
cms/src/lib/components/Calendar/CalendarArrow.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export let left = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<svg class:left on:click xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||||
|
<path fill="#c4d9fd" d="M0 256c0 141.2 114.8 256 256 256V0A256.3 256.3 0 000 256z"/>
|
||||||
|
<path fill="#c4d9fd" d="M256 0v512c141.2 0 256-114.8 256-256S397.2 0 256 0z"/>
|
||||||
|
<path fill="#5286fa" d="M226 115.4a23.3 23.3 0 00-33 33L300.7 256 193 363.7a23.3 23.3 0 1033 32.9l124-124.1a23.3 23.3 0 000-33l-124-124z"/></svg>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
svg {
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
padding: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
22
cms/src/lib/components/Calendar/calendarize.ts
Normal file
22
cms/src/lib/components/Calendar/calendarize.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
//Modify by Oom
|
||||||
|
//code from https://www.npmjs.com/package/calendarize
|
||||||
|
export default function (target?: Date|string, offset=0) {
|
||||||
|
let i=0, j=0, week = Array(7)
|
||||||
|
const out=[], date = new Date(target || new Date);
|
||||||
|
const year = date.getFullYear(), month = date.getMonth();
|
||||||
|
// day index (of week) for 1st of month
|
||||||
|
let first = new Date(year, month, 1 - (offset | 0)).getDay();
|
||||||
|
|
||||||
|
// how many days there are in this month
|
||||||
|
const days = new Date(year, month+1, 0).getDate();
|
||||||
|
|
||||||
|
while (i < days) {
|
||||||
|
for (j=0, week=Array(7); j < 7;) {
|
||||||
|
while (j < first) week[j++] = 0;
|
||||||
|
week[j++] = ++i > days ? 0 : i;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
out.push(week);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
191
cms/src/lib/components/Calendar2/Calendar.svelte
Normal file
191
cms/src/lib/components/Calendar2/Calendar.svelte
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import Calendar from "./CalendarContent.svelte";
|
||||||
|
export let locale = "en" as (keyof typeof text_labels)|(keyof typeof text_months);
|
||||||
|
export let buddhist = false
|
||||||
|
const text_labels = {
|
||||||
|
en: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
|
||||||
|
th: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'],
|
||||||
|
}
|
||||||
|
const text_months = {
|
||||||
|
en: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||||
|
th: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
|
||||||
|
}
|
||||||
|
const labels = (locale in text_labels)? text_labels[locale]:text_labels.en
|
||||||
|
const months = (locale in text_months)? text_months[locale]:text_months.en
|
||||||
|
|
||||||
|
let headers: string[] = [];
|
||||||
|
let now = new Date();
|
||||||
|
let year = now.getFullYear(); // this is the month & year displayed
|
||||||
|
let month = now.getMonth();
|
||||||
|
let eventText="Click an item or date";
|
||||||
|
|
||||||
|
var days: { name:string,enabled:boolean,date: Date }[] = []; // The days to display in each box
|
||||||
|
|
||||||
|
function randInt(max: number) {
|
||||||
|
return Math.floor(Math.random()*max)+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Calendar Component just displays stuff in a row & column. It has no knowledge of dates.
|
||||||
|
// The items[] below are placed (by you) in a specified row & column of the calendar.
|
||||||
|
// You need to call findRowCol() to calc the row/col based on each items start date. Each date box has a Date() property.
|
||||||
|
// And, if an item overlaps rows, then you need to add a 2nd item on the subsequent row.
|
||||||
|
var items: (
|
||||||
|
{ title: string; className: string; date: Date; len: number; isBottom?: boolean;
|
||||||
|
detailHeader?: string; detailContent?: string; vlen?: number; startCol?:number;startRow?:number}
|
||||||
|
)[] = [];
|
||||||
|
|
||||||
|
function initMonthItems() {
|
||||||
|
let y = year;
|
||||||
|
let m = month;
|
||||||
|
let d1=new Date(y,m,randInt(7)+7);
|
||||||
|
items=[
|
||||||
|
{title:"11:00 Task Early in month",className:"task--primary",date:new Date(y,m,randInt(6)),len:randInt(4)+1},
|
||||||
|
{title:"7:30 Wk 2 tasks",className:"task--warning",date:d1,len:randInt(4)+2},
|
||||||
|
{title:"Overlapping Stuff (isBottom:true)",date:d1,className:"task--info",len:4,isBottom:true},
|
||||||
|
{title:"10:00 More Stuff to do",date:new Date(y,m,randInt(7)+14),className:"task--info",len:randInt(4)+1,detailHeader:"Difficult",detailContent:"But not especially so"},
|
||||||
|
{title:"All day task",date:new Date(y,m,randInt(7)+21),className:"task--danger",len:1,vlen:2},
|
||||||
|
];
|
||||||
|
|
||||||
|
//This is where you calc the row/col to put each dated item
|
||||||
|
for (let i of items) {
|
||||||
|
let rc = findRowCol(i.date);
|
||||||
|
if (rc == null) {
|
||||||
|
console.log('didn`t find date for ',i);
|
||||||
|
console.log(i.date);
|
||||||
|
console.log(days);
|
||||||
|
i.startCol = i.startRow = 0;
|
||||||
|
} else {
|
||||||
|
i.startCol = rc.col;
|
||||||
|
i.startRow = rc.row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: month,year,initContent();
|
||||||
|
|
||||||
|
// choose what date/day gets displayed in each date box.
|
||||||
|
function initContent() {
|
||||||
|
headers = labels;
|
||||||
|
initMonth();
|
||||||
|
initMonthItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMonth() {
|
||||||
|
days = [];
|
||||||
|
let monthAbbrev = months[month].slice(0,3);
|
||||||
|
let nextMonthAbbrev = months[(month+1)%12].slice(0,3);
|
||||||
|
// find the last Monday of the previous month
|
||||||
|
var firstDay = new Date(year, month, 1).getDay();
|
||||||
|
//console.log('fd='+firstDay+' '+dayNames[firstDay]);
|
||||||
|
var daysInThisMonth = new Date(year, month+1, 0).getDate();
|
||||||
|
var daysInLastMonth = new Date(year, month, 0).getDate();
|
||||||
|
var prevMonth = month==0 ? 11 : month-1;
|
||||||
|
|
||||||
|
// show the days before the start of this month (disabled) - always less than 7
|
||||||
|
for (let i=daysInLastMonth-firstDay;i<daysInLastMonth;i++) {
|
||||||
|
let d = new Date(prevMonth==11?year-1:year,prevMonth,i+1);
|
||||||
|
days.push({name:''+(i+1),enabled:false,date:d,});
|
||||||
|
}
|
||||||
|
// show the days in this month (enabled) - always 28 - 31
|
||||||
|
for (let i=0;i<daysInThisMonth;i++) {
|
||||||
|
let d = new Date(year,month,i+1);
|
||||||
|
if (i==0) days.push({name:monthAbbrev+' '+(i+1),enabled:true,date:d,});
|
||||||
|
else days.push({name:''+(i+1),enabled:true,date:d,});
|
||||||
|
//console.log('i='+i+' dt is '+d+' date() is '+d.getDate());
|
||||||
|
}
|
||||||
|
// show any days to fill up the last row (disabled) - always less than 7
|
||||||
|
for (let i=0;days.length%7;i++) {
|
||||||
|
let d = new Date((month==11?year+1:year),(month+1)%12,i+1);
|
||||||
|
if (i==0) days.push({name:nextMonthAbbrev+' '+(i+1),enabled:false,date:d,});
|
||||||
|
else days.push({name:''+(i+1),enabled:false,date:d,});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findRowCol(dt:Date) {
|
||||||
|
for (let i=0;i<days.length;i++) {
|
||||||
|
let d = days[i].date;
|
||||||
|
if (d.getFullYear() === dt.getFullYear()
|
||||||
|
&& d.getMonth() === dt.getMonth()
|
||||||
|
&& d.getDate() === dt.getDate())
|
||||||
|
return {row:Math.floor(i/7)+2,col:i%7+1};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function itemClick(e: { date: { toString: () => string; }; }) {
|
||||||
|
eventText='itemClick '+JSON.stringify(e) + ' localtime='+e.date.toString();
|
||||||
|
}
|
||||||
|
function dayClick(e: { date: { toString: () => string; }; }) {
|
||||||
|
eventText='onDayClick '+JSON.stringify(e) + ' localtime='+e.date.toString();
|
||||||
|
}
|
||||||
|
function headerClick(e: any) {
|
||||||
|
eventText='onHheaderClick '+JSON.stringify(e);
|
||||||
|
}
|
||||||
|
function next() {
|
||||||
|
month++;
|
||||||
|
if (month == 12) {
|
||||||
|
year++;
|
||||||
|
month=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function prev() {
|
||||||
|
if (month==0) {
|
||||||
|
month=11;
|
||||||
|
year--;
|
||||||
|
} else {
|
||||||
|
month--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="calendar-container">
|
||||||
|
<div class="calendar-header">
|
||||||
|
<h1>
|
||||||
|
<button on:click={()=>year--}>≪</button>
|
||||||
|
<button on:click={()=>prev()}><</button>
|
||||||
|
{months[month]} {year+ (buddhist?543:0)}
|
||||||
|
<button on:click={()=>next()}>></button>
|
||||||
|
<button on:click={()=>year++}>≫</button>
|
||||||
|
</h1>
|
||||||
|
{eventText}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Calendar
|
||||||
|
{headers}
|
||||||
|
{days}
|
||||||
|
{items}
|
||||||
|
on:dayClick={(e)=>dayClick(e.detail)}
|
||||||
|
on:itemClick={(e)=>itemClick(e.detail)}
|
||||||
|
on:headerClick={(e)=>headerClick(e.detail)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.calendar-container {
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #fff;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
.calendar-header {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
background: #eef;
|
||||||
|
border-bottom: 1px solid rgba(166, 168, 179, 0.12);
|
||||||
|
}
|
||||||
|
.calendar-header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.calendar-header button {
|
||||||
|
background: #eef;
|
||||||
|
border: 1px ;
|
||||||
|
padding: 6;
|
||||||
|
color: rgba(81, 86, 93, 0.7);
|
||||||
|
cursor: pointer;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
222
cms/src/lib/components/Calendar2/CalendarContent.svelte
Normal file
222
cms/src/lib/components/Calendar2/CalendarContent.svelte
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
<div class="calendar">
|
||||||
|
{#each headers as header}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<span class="day-name" on:click={()=>dispatch('headerClick',header)}>{header}</span>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#each days as day}
|
||||||
|
{#if day.enabled}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<span class="day" on:click={()=>dispatch('dayClick',day)}>{day.name}</span>
|
||||||
|
{:else}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<span class="day day-disabled" on:click={()=>dispatch('dayClick',day)}>{day.name}</span>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#each items as item}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<section
|
||||||
|
on:click={()=>dispatch('itemClick',item)}
|
||||||
|
class="task {item.className}"
|
||||||
|
style="grid-column: {item.startCol} / span {item.len};
|
||||||
|
grid-row: {item.startRow};
|
||||||
|
align-self: {item.isBottom?'end':'center'};"
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
{#if item.detailHeader}
|
||||||
|
<div class="task-detail">
|
||||||
|
<h2>{item.detailHeader}</h2>
|
||||||
|
<p>{item.detailContent}</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {createEventDispatcher, onMount} from 'svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {any[]}
|
||||||
|
*/
|
||||||
|
export var headers = [];
|
||||||
|
/**
|
||||||
|
* @type {any[]}
|
||||||
|
*/
|
||||||
|
export let days = [];
|
||||||
|
/**
|
||||||
|
* @type {any[]}
|
||||||
|
*/
|
||||||
|
export let items = [];
|
||||||
|
|
||||||
|
let dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.calendar {
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
grid-template-columns: repeat(7, minmax(120px, 1fr));
|
||||||
|
grid-template-rows: 50px;
|
||||||
|
grid-auto-rows: 120px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.day {
|
||||||
|
border-bottom: 1px solid rgba(166, 168, 179, 0.12);
|
||||||
|
border-right: 1px solid rgba(166, 168, 179, 0.12);
|
||||||
|
text-align: right;
|
||||||
|
padding: 14px 20px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #98a0a6;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 7) {
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 1):nth-of-type(-n + 7) {
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 8):nth-of-type(-n + 14) {
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 15):nth-of-type(-n + 21) {
|
||||||
|
grid-row: 3;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 22):nth-of-type(-n + 28) {
|
||||||
|
grid-row: 4;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 29):nth-of-type(-n + 35) {
|
||||||
|
grid-row: 5;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(n + 36):nth-of-type(-n + 42) {
|
||||||
|
grid-row: 6;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 1) {
|
||||||
|
grid-column: 1/1;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 2) {
|
||||||
|
grid-column: 2/2;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 3) {
|
||||||
|
grid-column: 3/3;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 4) {
|
||||||
|
grid-column: 4/4;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 5) {
|
||||||
|
grid-column: 5/5;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 6) {
|
||||||
|
grid-column: 6/6;
|
||||||
|
}
|
||||||
|
.day:nth-of-type(7n + 7) {
|
||||||
|
grid-column: 7/7;
|
||||||
|
}
|
||||||
|
.day-name {
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #e9a1a7;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid rgba(166, 168, 179, 0.12);
|
||||||
|
line-height: 50px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.day-disabled {
|
||||||
|
color: rgba(152, 160, 166, 0.5);
|
||||||
|
background-color: #ffffff;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 40 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23fdf9ff' fill-opacity='1' fill-rule='evenodd'%3E%3Cpath d='M0 40L40 0H20L0 20M40 40V20L20 40'/%3E%3C/g%3E%3C/svg%3E");
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task {
|
||||||
|
border-left-width: 3px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 10px;
|
||||||
|
border-left-style: solid;
|
||||||
|
font-size: 14px;
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
z-index:2;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
.task--warning {
|
||||||
|
border-left-color: #fdb44d;
|
||||||
|
background: #fef0db;
|
||||||
|
color: #fc9b10;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
.task--danger {
|
||||||
|
border-left-color: #fa607e;
|
||||||
|
grid-column: 2 / span 3;
|
||||||
|
grid-row: 3;
|
||||||
|
margin-top: 15px;
|
||||||
|
background: rgba(253, 197, 208, 0.7);
|
||||||
|
color: #f8254e;
|
||||||
|
}
|
||||||
|
.task--info {
|
||||||
|
border-left-color: #4786ff;
|
||||||
|
margin-top: 15px;
|
||||||
|
background: rgba(218, 231, 255, 0.7);
|
||||||
|
color: #0a5eff;
|
||||||
|
}
|
||||||
|
.task--primary {
|
||||||
|
background: #4786ff;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 14px;
|
||||||
|
color: #f00;
|
||||||
|
box-shadow: 0 10px 14px rgba(71, 134, 255, 0.4);
|
||||||
|
}
|
||||||
|
.task-detail {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
background: #efe;
|
||||||
|
border: 1px solid rgba(166, 168, 179, 0.2);
|
||||||
|
color: #100;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.task-detail:after, .task-detail:before {
|
||||||
|
bottom: 100%;
|
||||||
|
left: 30%;
|
||||||
|
border: solid transparent;
|
||||||
|
content: " ";
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.task-detail:before {
|
||||||
|
border-bottom-color: rgba(166, 168, 179, 0.2);
|
||||||
|
border-width: 8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
.task-detail:after {
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
border-width: 6px;
|
||||||
|
margin-left: -6px;
|
||||||
|
}
|
||||||
|
.task-detail h2 {
|
||||||
|
font-size: 15px;
|
||||||
|
margin: 0;
|
||||||
|
color: #91565d;
|
||||||
|
}
|
||||||
|
.task-detail p {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(81, 86, 93, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
5
cms/src/lib/data/qualify-exam.json
Normal file
5
cms/src/lib/data/qualify-exam.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
[
|
||||||
|
{"id":20,"date":"2023/03/25","detail":"ประกาศรับสมัครสอบและคัดเลือกบุคคลเข้ารับราชการเป็นลูกจ้างชั่วคราว","institute":"สำนักอนามัย","time":"๕/๒๕๖๕"},
|
||||||
|
{"id":19,"date":"2023/03/23","detail":"ประกาศรายชื่อผู้มีสิทธิเข้ารับการสอบคัดเลือกบุคคลภายนอกช่วยปฎิบัติราชการ","institute":"สำนักการแพทย์","time":"๔/๒๕๖๔"},
|
||||||
|
{"id":18,"date":"2023/03/20","detail":"ประกาศกรุงเทพมหานคร เรื่อง ประกาศผู้ชนะการเสนอราคา จ้างเหมาซ่อมแซมป้ายชื่อ","institute":"สำนักวัฒนธรรม กีฬาและการท่องเที่ยว","time":"๔/๒๕๖๓"}
|
||||||
|
]
|
||||||
4
cms/src/lib/data/qualify-exam.ts
Normal file
4
cms/src/lib/data/qualify-exam.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import exams from "./qualify-exam.json"
|
||||||
|
export async function getExams(){
|
||||||
|
return exams
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
<div class="p-10 max-w-4xl place-content-center ">
|
<div class="p-5 max-w-4xl place-content-center ">
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,5 @@ export const load: PageServerLoad = async () => {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
export const load = (async () => {
|
export const load = (async () => {
|
||||||
return getContact()
|
return await getContact()
|
||||||
}) satisfies PageServerLoad
|
}) satisfies PageServerLoad
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,54 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PageData } from './$types'
|
import 'dayjs/locale/th.js';
|
||||||
|
import 'dayjs/locale/zh-cn.js';
|
||||||
|
import 'dayjs/locale/es.js';
|
||||||
|
import 'dayjs/locale/ar-dz.js';
|
||||||
|
// มันรองรับ พ.ศ. ใน dayjs แต่ใน velte-calendar ไม่ได้เอาไปใช้ ยังหาวิธีแก้หัวปฎิทินไม่ได้ยังเป็น พ.ศ.
|
||||||
|
import buddhistEra from 'dayjs/plugin/buddhistEra'
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
dayjs.extend(buddhistEra)
|
||||||
|
import { InlineCalendar, Swappable, themes } from 'svelte-calendar';
|
||||||
|
import { onDestroy } from 'svelte';
|
||||||
|
const locales = ['th','en', 'es', 'zh-cn', 'ar-dz'];
|
||||||
|
$: dayjs.locale(locale);
|
||||||
|
onDestroy(() => dayjs.locale('en'));
|
||||||
|
|
||||||
|
import Calendar2 from '$lib/components/Calendar2/Calendar.svelte';
|
||||||
|
import Calendar from '$lib/components/Calendar/Calendar.svelte';
|
||||||
|
const today = new Date
|
||||||
|
const locale = "th"
|
||||||
|
const buddhist = true //buddhist calendar + 543
|
||||||
|
let year = today.getFullYear()
|
||||||
|
let month = today.getMonth()
|
||||||
|
|
||||||
import ver from "$lib/ver.json"
|
import ver from "$lib/ver.json"
|
||||||
|
import type { PageData } from './$types'
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<h1 class="text-4xl">เกี่ยวกับ {data.company_name}</h1>
|
||||||
<h1 class="text-4xl">{data.company_name}</h1>
|
|
||||||
|
|
||||||
<div>{data.description}</div>
|
<div>{data.description}</div>
|
||||||
<div>{ver.version}</div>
|
<div>{ver.version}</div>
|
||||||
<div>{ver.builddate}</div>
|
<div>{ver.builddate}</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl">svelte-calendar</h2>
|
||||||
|
<p>3rd svelte-calendar ไม่รองรับ พ.ศ.</p>
|
||||||
|
<!-- note: Locale is not reactive -->
|
||||||
|
<Swappable value={{ locale }} vertical={false} >
|
||||||
|
<InlineCalendar theme={themes.light} />
|
||||||
|
</Swappable>
|
||||||
|
|
||||||
|
<h2 class="text-2xl">Custom Calendar1</h2>
|
||||||
|
<div>
|
||||||
|
Calendar ทำเองยังไม่รองรับการแสดง event ในวัน
|
||||||
|
</div>
|
||||||
|
<Calendar {year} {month} {locale} {buddhist}/>
|
||||||
|
|
||||||
|
<h2 class="text-2xl">Custom Calendar2</h2>
|
||||||
|
<div>
|
||||||
|
ทำเองรองรับการแสดง event และคลิ้กได้ ได้แต่ยังปรับโค้ดไม่เรียบร้อย
|
||||||
|
</div>
|
||||||
|
<Calendar2 {locale} {buddhist} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,35 @@
|
||||||
<h1 class="text-4xl">การสอบแข่งขัน</h1>
|
<script lang="ts">
|
||||||
|
import 'dayjs/locale/th.js';
|
||||||
|
import 'dayjs/locale/zh-cn.js';
|
||||||
|
import 'dayjs/locale/es.js';
|
||||||
|
import 'dayjs/locale/ar-dz.js';
|
||||||
|
// มันรองรับ พ.ศ. ใน dayjs แต่ใน velte-calendar ไม่ได้เอาไปใช้ ยังหาวิธีแก้หัวปฎิทินไม่ได้ยังเป็น พ.ศ.
|
||||||
|
import buddhistEra from 'dayjs/plugin/buddhistEra'
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
dayjs.extend(buddhistEra)
|
||||||
|
import { InlineCalendar, Swappable, themes } from 'svelte-calendar';
|
||||||
|
import { onDestroy } from 'svelte';
|
||||||
|
|
||||||
fdsafda
|
const locales = ['th','en', 'es', 'zh-cn', 'ar-dz'];
|
||||||
fdsafda sdaf
|
let format = 'DD/MM/BBBB'
|
||||||
sdaffsdasaf rfffffffffffffffff fffffffffffffffffffffffff ffffffffffff fgedfgfdgfdsg
|
let locale = 'th';
|
||||||
fedsddddddddddddd ddddddddddddddd ddddddddd d d d d d d d d d d d d xxxx
|
|
||||||
|
$: dayjs.locale(locale);
|
||||||
|
|
||||||
|
onDestroy(() => dayjs.locale('en'));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<h1 class="text-4xl">การสอบแข่งขัน</h1>
|
||||||
|
<!-- note: Locale is not reactive -->
|
||||||
|
<Swappable value={{ locale }} vertical={false} >
|
||||||
|
<InlineCalendar theme={themes.light} {format} />
|
||||||
|
</Swappable>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
{#each locales as loc}
|
||||||
|
<button on:click={() => (locale = loc)} class:selected={locale === loc}>
|
||||||
|
{loc}
|
||||||
|
</button> |
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
|
||||||
8
cms/src/routes/qualifying/+page.server.ts
Normal file
8
cms/src/routes/qualifying/+page.server.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
import {getExams} from "$lib/data/qualify-exam"
|
||||||
|
import type { PageServerLoad } from './$types'
|
||||||
|
export const load: PageServerLoad = async () => {
|
||||||
|
const exams = await getExams()
|
||||||
|
return {exams}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,28 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import type { PageData } from './$types'
|
||||||
|
export let data: PageData;
|
||||||
|
const exams = data.exams
|
||||||
|
</script>
|
||||||
|
|
||||||
<h1 class="text-4xl">การสอบคัดเลือก</h1>
|
<h1 class="text-4xl">การสอบคัดเลือก</h1>
|
||||||
|
|
||||||
<button class="btn btn-outline">Button</button>
|
้<h1 class="text-2xl">รายการสอบ</h1>
|
||||||
<button class="btn btn-outline btn-primary">Button</button>
|
<div class="overflow-x-auto">
|
||||||
<button class="btn btn-outline btn-secondary">Button</button>
|
<table class="table table-compact w-full">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>วันที่</th>
|
||||||
|
<th>การสอบ</th>
|
||||||
|
<th>หน่วยงาน</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each exams as exam}
|
||||||
|
<tr>
|
||||||
|
<th><a href={"/exams/"+exam.id}>{exam.date}</a></th>
|
||||||
|
<td>{exam.detail}</td>
|
||||||
|
<td>{exam.institute}</td>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
@ -15,6 +15,7 @@ const config = {
|
||||||
],
|
],
|
||||||
|
|
||||||
kit: {
|
kit: {
|
||||||
|
|
||||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@ export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue