# 勞基法計算機
### vue.js 初體驗
----
[Yuren Ju](https://github.com/yurenju) - [g0v 零時政府](http://g0v.tw/zh-TW/index.html)
---
## 起因
![](https://i.imgur.com/4ENWvcT.png)
---
大家都自己計算造表格,不如寫一個小計算機讓大家可以在上面試算與分享?
---
就這樣,應該馬上就做好了!
![](https://i.imgur.com/cT2rldf.jpg)
---
先來看一下 [勞基法](http://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=N0030001) 好了!
![](https://i.imgur.com/RlCe44X.png)
---
![](http://i.giphy.com/l2SpOXeMPHNGOqiRi.gif)
---
![](https://i.imgur.com/xcX7oAO.png)
BTW, 這只是其中的一條
---
![](http://i.imgur.com/2yzv4io.jpg)
---
![](http://i.giphy.com/OYL1FqJ4Qs6Iw.gif)
---
等等等等,先跳過太複雜的變形工時
我們還是從簡單的問題開始好了
---
## 請問一位月薪 36,000 元的勞工
### 平日加班一小時的薪水應該是多少?
---
# 大約 300 元?
每個月工作天約二十天,每天正常工作時數是八小時
最低加班費的算法是乘以 1 ⅓
`36000 / 20 / 8 * (4 / 3) = 300`
---
# 錯
---
### `36000 / 30 / 8 * (4 / 3) = 200`
<div style="font-size:0.5em;">
<a href="http://laws.mol.gov.tw/Chi/FLAW/FLAWDOC03.asp?keyword=&lc1=FL014930%2C+20150701%2C+24&sdate=&edate=&datatype=etype&recordNo=7">勞動 2 字第 0960130677 號 函</a>
:原約定月薪給付總額相當於 240 小時者(即「平日每小時工資額」係以月薪總額除以 30 再除以 8 核計者)
</div>
---
## 所以你假日也是有支薪的
### 很合理吧?
---
## 請問一位月薪 36,000 元的勞工
週六加班第一小時的 <span style="color:red;">最低法定薪資</span> 應該是多少?
<div style="font-size:0.5em;">
假設該勞工平常日都工作八小時
</div>
---
# 新台幣 50 元整 💢
因為你假日有給薪喔~
所以週六來加班的話根據勞基法 24 條額外加給三分之一以上
<div style="font-size:0.5em;">
注意這邊是最低法定薪資,但是雇主其實是可以給你更高
</div>
---
## 因為太扯了
所以我有[打電話](https://medium.com/@yurenju/勞基法修法計算機-8f570d45d4ae)去台北市勞動局確認過
目前勞動檢查確實是這樣認定
---
好吧雖然很扯,但搞清楚規則之後
還是可以照計畫作出來
![](https://i.imgur.com/cT2rldf.jpg)
---
[g0v 勞基法修法計算機](https://g0v.github.io/workweek/)
![](https://i.imgur.com/h3NYYJa.png)
---
## React.js vs Angular.js vs Vue.js
----
[Vue.js comparision](https://cn.vuejs.org/guide/comparison.html)
![](http://i.giphy.com/8rVWwln2VkXh6.gif)
---
## 其實
不管用框架或是純寫 JavaScript 都可以完成,我自己使用框架主要是要讓開發速度加快。熟悉了開發工具不論用哪套其實都可以達到目的
---
## 背景
1. 這是我第一個 Vue.js 專案
2. 以前寫過 Angular.js 跟 React.js 但是經驗都不算多
3. 原本覺得這是週末小專案,想要很快速寫完
4. 我想用 side project 熟悉一些新工具
---
### 花個幾分鐘看了一下 vue.js 的文件⋯
這是現代版本的 Angular.js 吧?
---
## 馬上看到的優點
1. 跟 Angular 十分類似,寫過 Angular 的人入手很快
2. 官方 cli 工具跟 webpack 無縫整合
3. 撰寫 component 十分簡易,可包裝在一個 .vue 檔案
* [Angular.js directive](https://docs.angularjs.org/guide/directive) vs [Vue.js Component](https://cn.vuejs.org/guide/components.html)
---
## 沒考慮多久就決定用 Vue.js 了
### (順便玩玩新工具)
---
## Template
```shell
$ npm install vue-cli
$ vue init webpack PROJECT_NAME
```
---
![](https://i.imgur.com/MpecUOb.png)
---
<img style="width: 35%;" src="https://i.imgur.com/aMgNYFB.png">
---
![](https://i.imgur.com/N3NKiQY.png)
---
![](https://i.imgur.com/I8euAKl.png)
---
![](https://i.imgur.com/yH64z5T.png)
---
![](https://i.imgur.com/N3NKiQY.png)
---
<img src="https://i.imgur.com/vtNbQOv.png" style="width: 60%;">
---
## main.js
```javascript=
import Vue from 'vue';
import App from './App';
new Vue({
el: 'body',
components: { App },
});
```
---
## index.html
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>workweek</title>
</head>
<body>
<app></app>
<!-- built files will be auto injected -->
</body>
</html>
```
---
## ES6 by babel.js!
* ES6 module!
* Object Literal Shorthand
```javascript=
import Vue from 'vue';
import App from './App';
new Vue({
el: 'body',
components: { App },
});
```
```javascript=
// ES5
new Vue({
el: 'body',
components: { App: App },
});
```
---
![](http://i.giphy.com/em4i0bDs9Hm2Q.gif)
---
ES6
* Arrow function
* `items.filter(item => item.is(Text));`
* Classes
* Destructuring assignment
* `var [a, b] = [1, 2];`
* [More](http://es6-features.org/)
---
## .Vue file
1. <template>
2. <script>
3. <style>
---
## App.vue
![](https://i.imgur.com/Z2eFJyw.png)
---
## Hello.vue
<img src="https://i.imgur.com/IBu01oz.png" style="width: 80%;">
---
![](https://i.imgur.com/yH64z5T.png)
---
<img src="https://i.imgur.com/9P9Gka0.png" style="width:80%">
---
### 雖然 Vue.js 提供了很好拆分小元件的寫法
身為一個新手而這又是個小週末專案
就把所有東西都到一個叫做 Workweek 的 vue component 吧 :D
---
![](http://i.giphy.com/Tr10zt02CSMOQ.gif)
---
![](https://i.imgur.com/pdSF3gM.png)
---
## 來看看專案裡面用到的 vue.js 功能
---
## Script 內的常用屬性
* components
* props
* data()
* computed()
* methods
---
```javascript=
export default {
components: {
Component1,
Component2
},
props: ['prop1', 'prop2'],
methods: {
method1 (reason) {
// ...
},
method2 () {
// ...
}
},
data () {
// {{data1}}
return {
data1: 'DATA1',
data2: 'DATA2',
data3: 'DATA3',
};
},
computed: {
// {{computed1}}
computed1() {
// ...
},
computed2() {
// ...
}
}
};
```
---
## data()
```javascript=
data () {
// ...
return {
reason: reason,
daynames: solutions.DAY_NAMES,
workhours: workhours,
assumingWorkHours: 240,
monthlyPay: monthlyPay,
expandDetail: false,
regularHoursPerDay: solutions.REGULAR_HOURS_PER_DAY
};
},
```
---
## computed()
```javascript=
export default {
data() { /* ... */ },
computed: {
hourlyPay: function () {
return parseFloat(this.monthlyPay / this.assumingWorkHours);
},
regularPay: function () {
return this.hourlyPay * 8 * 7;
}
}
};
```
---
## methods
```javascript=
export default {
methods: {
toggleExpanding: function (evt) {
this.expandDetail = !this.expandDetail;
}
}
};
```
---
## Template 內常用語法
---
[Two way binding](https://vuejs.org/guide/#Two-way-Binding)
<img src="https://i.imgur.com/euklIgV.png" style="width: 60%;">
---
## Template 內常用語法
* `v-model`
* `v-for`
* `v-show / v-if`
* `v-bind:model` (簡寫 :model)
* `v-on:click` (簡寫 @click)
* `{{ variable }}`
* `{{{ html }}}`
---
## 很順利地寫完週末小專案了
但是技術債很快就來討債了:
是誰說要所有東西寫在一個元件裡面的?
[很悲劇的 Workweek.vue](https://github.com/g0v/workweek/blob/50d126330ddf73cc71f67c90be12c013ec27adae/src/components/Workweek.vue)
---
## Refactoring
![](https://i.imgur.com/yTUfW7F.png)
---
![](https://i.imgur.com/Em0menN.jpg)
---
## offday-condition diagram
![](https://i.imgur.com/ltPp3Rm.png)
---
## offday-condition component
```htmlmixed=
<offday-condition
v-bind:reason="reason"
v-on:reason-changed="reasonChanged">
</offday-condition>
```
簡寫
```htmlmixed=
<offday-condition
:reason="reason"
@reason-changed="reasonChanged">
</offday-condition>
```
---
OffdayCondition.vue script
```javascript=
export default {
props: ['reason'],
watch: {
reason (val) {
this.$dispatch('reason-changed', val);
}
}
};
```
Workweek.vue script
```javascript=
reasonChanged (reason) {
this.reason = reason;
}
```
---
## Workweek.vue
```javascript=
export default {
computed: {
currentSolution () {
return solutions.current(this.workhours, this.hourlyPay, this.reason);
},
oneRestOneOffSolution () {
return solutions.oneRestOneOff(this.workhours, this.hourlyPay, this.reason);
},
twoOffSolution () {
return solutions.twoOff(this.workhours, this.hourlyPay, this.reason);
}
}
}
```
---
## current-solution component
```htmlmixed=
<current-solution
:solution="currentSolution"
:regular-pay="regularPay"
:overtime-pay-winner="mostOvertimePay.current"
:expand="expandDetail">
</current-solution>
```
---
![](https://i.imgur.com/yWiuvQW.png)
---
## 結論
* 現行勞基法很奇怪,確實要修。
* 但是目前修法方向很奇怪
* vue.js 是個好東西啊⋯⋯
* 語法簡單,很像 Angular
* 容易包裝元件
* 官方的 cli 工具直接整合了 webpack, babel.js
* 從我的經驗來看,開發小型專案很好用
* 還有時間的話可以講一下 static website deploy
* 電梯向下 👇
---
## 如果你的專案是純前端專案
deploy 到 github pages 是個不錯的選擇
---
<img src="https://i.imgur.com/nlOtJ1D.png" style="width:80%;">
---
## package.json
```javascript=
{
"name": "workweek",
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js",
"test": "echo \"No tests\"",
"lint": "eslint --ext .js,.vue src",
"deploy": "node build/deploy.js"
}
}
```
---
## .travis.yml
```yaml=
language: node_js
node_js:
- '4'
env:
global:
- GH_REF=github.com/g0v/workweek.git
# GH_TOKEN
- secure: "..."
cache: node_modules
script:
- npm run build
after_success: npm run deploy
```
---
## deploy.js
```javascript=
require('shelljs/global');
rm('-rf', 'out');
exec('git clone "https://' + env.GH_TOKEN +
'@' + env.GH_REF + '" --depth 1 -b gh-pages out');
pushd('out');
exec('git config user.name "Automatic Commit"');
exec('git config user.email "workweek@g0v.tw"');
exec('git rm -rf .');
cp('-r', '../dist/', '.');
exec('git add .');
exec('git commit -m "Automatic commit: ' + Date() + '"');
exec('git push "https://' + env.GH_TOKEN +
'@' + env.GH_REF + '" gh-pages', {silent: true});
popd();
exit(0);
```
{"metaMigratedAt":"2023-06-14T11:48:35.651Z","metaMigratedFrom":"YAML","title":"勞基法計算機","breaks":true,"disqus":"yurenju-hackmd","contributors":"[]"}