Skip to content

Commit

Permalink
feat: サイコロウィジェット (#73)
Browse files Browse the repository at this point in the history
* feat: サイコロウィジェット

* Update CHANGELOG
  • Loading branch information
1673beta authored Jul 6, 2024
1 parent c038c15 commit d93e6b6
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 41 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG_engawa.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
- ノートの自動削除機能を追加

### Client
-
- ダイスウィジェットを追加

### Server
- 管理者アカウントを別サーバーに移行できるように
Expand Down
14 changes: 14 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11580,6 +11580,20 @@ export interface Locale extends ILocale {
*/
"lookup": string;
};
"_dice": {
/**
* サイコロを振る
*/
"rollDice": string;
/**
* サイコロの数
*/
"diceCount": string;
/**
* サイコロの面数
*/
"diceFaces": string;
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
5 changes: 5 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3090,3 +3090,8 @@ _searchOrApShow:
question: "照会を行いますか?"
search: "検索"
lookup: "照会"

_dice:
rollDice: "サイコロを振る"
diceCount: "サイコロの数"
diceFaces: "サイコロの面数"
1 change: 1 addition & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"lint": "pnpm typecheck && pnpm oxlint"
},
"dependencies": {
"@dice-roller/rpg-dice-roller": "^5.5.0",
"@discordapp/twemoji": "15.0.3",
"@github/webauthn-json": "2.1.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
Expand Down
87 changes: 87 additions & 0 deletions packages/frontend/src/components/MkDice.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<template>
<div class="zmdxowus">
<div>
<MkInput v-model="diceCount" small type="text" class="input">
<template #label>{{ i18n.ts._dice.diceCount }}</template>
</MkInput>
</div>
<div>
<MkInput v-model="diceFaces" small type="text" class="input">
<template #label>{{ i18n.ts._dice.diceFaces }}</template>
</MkInput>
</div>
<div>
<MkButton large primary style="margin: 0 auto;" @click="rollDice">
<i class="ti ti-dice-2"></i>
{{ i18n.ts._dice.rollDice }}
</MkButton>
</div>
<div v-if="diceResult" class="result">{{ diceResult }}</div>
<div v-if="showMinTotal" class="option">{{ diceMinTotal }}</div>
<div v-if="showMaxTotal" class="option">{{ diceMaxTotal }}</div>
<dic v-if="showAverageTotal" class="option">{{ diceAverageTotal }}</dic>
</div>
</template>

<script lang="ts" setup>
import { Ref, ref } from 'vue';
import { DiceRoll } from '@dice-roller/rpg-dice-roller';
import MkInput from '@/components/MkInput.vue';
import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n';
const props = withDefaults(defineProps<{
showMinTotal?: boolean;
showMaxTotal?: boolean;
showAverageTotal?: boolean;
}>(), {
showMinTotal: false,
showMaxTotal: false,
showAverageTotal: false,
});
const diceCount = ref(1);
const diceFaces = ref(6);
const diceResult: Ref<number | null> = ref(null);
const diceMinTotal: Ref<number | null> = ref(null);
const diceMaxTotal: Ref<number | null> = ref(null);
const diceAverageTotal: Ref<number | null> = ref(null);
const rollDice = () => {
let roll = new DiceRoll(`${diceCount.value}d${diceFaces.value}`);
if (diceCount.value > 999) {
return;
}
diceResult.value = roll.total;
diceMinTotal.value = roll.minTotal;
diceMaxTotal.value = roll.maxTotal;
diceAverageTotal.value = roll.averageTotal;
}
</script>

<style lang="scss" scoped>
.zmdxowus {
padding: 8px 16px;
> div {
margin: 8px 0;
}
> .input {
flex: 1 1 auto;
padding: 8px;
}
> .result {
text-align: center;
margin: auto;
}
> .option {
padding: 8px 0;
text-align: left;
}
}
</style>
67 changes: 67 additions & 0 deletions packages/frontend/src/widgets/WidgetDice.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<template>
<div class="_monospace" :class="[$style.root, {_panel: !widgetProps.transparent}]">
<MkDice
:showMinTotal="widgetProps.showMinTotal"
:showMaxTotal="widgetProps.showMaxTotal"
:showAverageTotal="widgetProps.showAverageTotal"
/>
</div>
</template>

<script lang="ts" setup>
import { Ref, ref } from 'vue';
import { GetFormResultType } from '@/scripts/form.js';
import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
import MkDice from '@/components/MkDice.vue';
import { i18n } from '@/i18n.js';
const name = 'dice';
const widgetPropsDef = {
transparent: {
type: 'boolean' as const,
default: false,
},
showMinTotal: {
type: 'boolean' as const,
default: false,
},
showMaxTotal: {
type: 'boolean' as const,
default: false,
},
showAverageTotal: {
type: 'boolean' as const,
default: false,
},
}
type WidgetProps = GetFormResultType<typeof widgetPropsDef>;
const props = defineProps<WidgetComponentProps<WidgetProps>>();
const emit = defineEmits<WidgetComponentEmits<WidgetProps>>();
const { widgetProps, configure } = useWidgetPropsManager(name,
widgetPropsDef,
props,
emit,
);
defineExpose<WidgetComponentExpose>({
name,
configure,
id: props.widget ? props.widget.id : null,
});
</script>

<style lang="scss" module>
.root {
position: relative;
padding: 16px 0;
> .input {
flex: 1 1 auto;
}
}
</style>
2 changes: 2 additions & 0 deletions packages/frontend/src/widgets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default function(app: App) {
app.component('WidgetUserList', defineAsyncComponent(() => import('./WidgetUserList.vue')));
app.component('WidgetClicker', defineAsyncComponent(() => import('./WidgetClicker.vue')));
app.component('WidgetBirthdayFollowings', defineAsyncComponent(() => import('./WidgetBirthdayFollowings.vue')));
app.component('WidgetDice', defineAsyncComponent(() => import('./WidgetDice.vue')));
}

export const widgets = [
Expand Down Expand Up @@ -65,4 +66,5 @@ export const widgets = [
'userList',
'clicker',
'birthdayFollowings',
'dice',
];
Loading

0 comments on commit d93e6b6

Please sign in to comment.