Skip to content

Commit

Permalink
Merge pull request #807 from ruchamahabal/forms
Browse files Browse the repository at this point in the history
  • Loading branch information
ruchamahabal committed Aug 22, 2023
2 parents d64f70a + 83d39a6 commit 28c9216
Show file tree
Hide file tree
Showing 63 changed files with 4,772 additions and 358 deletions.
5 changes: 4 additions & 1 deletion .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@
b55d6e27af6bd274dfa47e66a3012ddec68ce798

# bulk formatting PWA frontend code
f37f15b2b5329e3b0b35891e1c4fd82f48562c6d
f37f15b2b5329e3b0b35891e1c4fd82f48562c6d

# bulk formatting PWA frontend code
920daa1a3ddccaefaf7b9348f850831d6e0a0e6b
2 changes: 2 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Frappe HR" />
<meta name="apple-mobile-web-app-status-bar-style" content="white" />
<!-- required for setting the status bar bg as white -->
<meta name="theme-color" content="#fff" />

<!-- PWA -->
<link
Expand Down
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"copy-html-entry": "cp ../hrms/public/frontend/index.html ../hrms/www/hrms.html"
},
"dependencies": {
"@ionic/vue": "^7.0.4",
"@ionic/vue-router": "^7.0.4",
"@ionic/vue": "^7.2.1",
"@ionic/vue-router": "^7.2.1",
"dayjs": "^1.11.7",
"feather-icons": "^4.28.0",
"frappe-ui": "^0.0.112",
Expand Down
37 changes: 37 additions & 0 deletions frontend/src/components/EmployeeAdvanceBalance.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<template>
<div
class="flex flex-col bg-white rounded-lg mt-5 overflow-auto"
v-if="props.items?.length"
>
<router-link
v-for="link in props.items"
:key="link.name"
:to="{ name: 'EmployeeAdvanceDetailView', params: { id: link.name } }"
class="flex flex-row p-3.5 items-center justify-between border-b cursor-pointer"
>
<EmployeeAdvanceItem :doc="link" />
</router-link>
<router-link
:to="{ name: 'EmployeeAdvanceFormView' }"
v-slot="{ navigate }"
>
<div class="flex flex-col bg-white w-full py-5 px-3.5 mt-0 border-none">
<Button @click="navigate" appearance="secondary" class="py-2">
Request an Advance
</Button>
</div>
</router-link>
</div>
<EmptyState message="You have no advances" v-else />
</template>
<script setup>
import EmployeeAdvanceItem from "@/components/EmployeeAdvanceItem.vue"
const props = defineProps({
items: {
type: Array,
},
})
</script>
80 changes: 80 additions & 0 deletions frontend/src/components/EmployeeAdvanceItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>
<div class="flex flex-col w-full justify-center gap-2.5">
<div class="flex flex-row items-center justify-between">
<div class="flex flex-row items-start gap-3 grow">
<WalletIcon class="h-4 w-4 mt-0.5 text-gray-500" />
<div class="flex flex-col items-start">
<div
v-if="props.doc.balance_amount"
class="text-xl font-bold text-gray-800 leading-6"
>
{{ `${currency} ${props.doc.balance_amount} /` }}
<span class="text-gray-600">
{{ `${currency} ${props.doc.paid_amount}` }}
</span>
</div>
<div v-else class="text-xl font-bold text-gray-800 leading-6">
{{ `${currency} ${props.doc.advance_amount}` }}
</div>
<div class="text-sm font-normal text-gray-500">
<span>
{{ props.doc.purpose }}
</span>
<span class="whitespace-pre"> &middot; </span>
<span class="whitespace-nowrap">
{{ postingDate }}
</span>
</div>
</div>
</div>
<div class="flex flex-row justify-end items-center gap-2">
<Badge :colorMap="colorMap" :label="props.doc.status" />
<FeatherIcon name="chevron-right" class="h-5 w-5 text-gray-500" />
</div>
</div>
<div
v-if="props.isTeamRequest"
class="flex flex-row items-center gap-2 pl-8"
>
<EmployeeAvatar :employeeID="props.doc.employee" />
<div class="text-sm text-gray-600 grow">
{{ props.doc.employee_name }}
</div>
</div>
</div>
</template>

<script setup>
import { FeatherIcon, Badge } from "frappe-ui"
import { computed, inject } from "vue"
import { getCurrencySymbol } from "@/data/currencies"
import EmployeeAvatar from "@/components/EmployeeAvatar.vue"
import WalletIcon from "@/components/icons/WalletIcon.vue"
const dayjs = inject("$dayjs")
const props = defineProps({
doc: {
type: Object,
},
isTeamRequest: {
type: Boolean,
default: false,
},
})
const colorMap = {
Paid: "green",
Unpaid: "yellow",
Claimed: "blue",
Returned: "gray",
"Partly Claimed and Returned": "yellow",
}
const currency = computed(() => getCurrencySymbol(props.doc.currency))
const postingDate = computed(() => {
return dayjs(props.doc.posting_date).format("D MMM")
})
</script>
13 changes: 13 additions & 0 deletions frontend/src/components/EmptyState.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div
class="text-sm text-gray-500 rounded-lg flex flex-col items-center bg-gray-100 p-5"
>
{{ props.message }}
</div>
</template>

<script setup>
const props = defineProps({
message: { type: String },
})
</script>
83 changes: 83 additions & 0 deletions frontend/src/components/ExpenseAdvancesTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<template>
<div class="flex flex-row justify-between items-center">
<h2 class="text-lg font-semibold text-gray-800">Settle against Advances</h2>
</div>

<div class="flex flex-col gap-2.5" v-if="expenseClaim.advances?.length">
<!-- Advance Card -->
<div
v-for="advance in expenseClaim.advances"
:key="advance.name"
class="flex flex-col bg-white border shadow-sm rounded-lg p-3.5"
:class="[
advance.selected ? 'border-blue-500' : '',
isReadOnly ? '' : 'cursor-pointer',
]"
@click="toggleAdvanceSelection(advance)"
>
<div class="flex flex-row justify-between items-center">
<div class="flex flex-row items-start gap-3">
<Input
type="checkbox"
class="mt-0.5"
v-model="advance.selected"
:disabled="isReadOnly"
/>
<div class="flex flex-col items-start gap-1">
<div class="text-lg font-semibold text-gray-800">
{{ advance.purpose || advance.employee_advance }}
</div>
<div class="flex flex-row items-center gap-3 justify-between">
<div class="text-sm font-normal text-gray-500">
{{
`Unclaimed Amount: ${currency} ${advance.unclaimed_amount}`
}}
</div>
</div>
</div>
</div>
<div class="flex flex-row items-center gap-2">
<span class="text-normal">
{{ currency }}
</span>
<Input
type="number"
class="w-20"
v-model="advance.allocated_amount"
@input="(v) => (advance.selected = v)"
@click.stop
:disabled="isReadOnly"
:max="advance.unclaimed_amount"
min="0"
/>
</div>
</div>
</div>
</div>
<EmptyState message="No advances found" v-else />
</template>
<script setup>
const props = defineProps({
expenseClaim: {
type: Object,
required: true,
},
currency: {
type: String,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
},
})
function toggleAdvanceSelection(advance) {
if (props.isReadOnly) return
advance.selected = !advance.selected
}
</script>
98 changes: 98 additions & 0 deletions frontend/src/components/ExpenseClaimItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<div class="flex flex-col w-full justify-center gap-2.5">
<div class="flex flex-row items-center justify-between">
<div class="flex flex-row items-start gap-3 grow">
<ExpenseIcon class="h-5 w-5 mt-0.5 text-gray-500" />
<div class="flex flex-col items-start">
<div class="text-lg font-normal text-gray-800">
{{ claimTitle }}
</div>
<div class="text-sm font-normal text-gray-500">
<span>
{{ `${currency} ${props.doc.total_claimed_amount}` }}
</span>
<span class="whitespace-pre"> &middot; </span>
<span class="whitespace-nowrap">
{{ claimDates }}
</span>
</div>
</div>
</div>
<div class="flex flex-row justify-end items-center gap-2">
<span
class="text-gray-600 bg-gray-100 font-medium rounded-lg text-xs px-2"
>
{{ props.doc.status }}
</span>
<Badge :colorMap="colorMap" :label="approvalStatus" />
<FeatherIcon name="chevron-right" class="h-5 w-5 text-gray-500" />
</div>
</div>
<div
v-if="props.isTeamRequest"
class="flex flex-row items-center gap-2 pl-8"
>
<EmployeeAvatar :employeeID="props.doc.employee" />
<div class="text-sm text-gray-600 grow">
{{ props.doc.employee_name }}
</div>
</div>
</div>
</template>

<script setup>
import { FeatherIcon, Badge } from "frappe-ui"
import { computed, inject } from "vue"
import { getCompanyCurrencySymbol } from "@/data/currencies"
import EmployeeAvatar from "@/components/EmployeeAvatar.vue"
import ExpenseIcon from "@/components/icons/ExpenseIcon.vue"
const dayjs = inject("$dayjs")
const props = defineProps({
doc: {
type: Object,
},
isTeamRequest: {
type: Boolean,
default: false,
},
})
const colorMap = {
Approved: "green",
Rejected: "red",
Pending: "yellow",
}
const claimTitle = computed(() => {
let title = props.doc.expense_type
if (props.doc.total_expenses > 1) {
title += ` & ${props.doc.total_expenses - 1} more`
}
return title
})
const claimDates = computed(() => {
if (!props.doc.from_date && !props.doc.to_date)
return dayjs(props.doc.posting_date).format("D MMM")
if (props.doc.from_date === props.doc.to_date) {
return dayjs(props.doc.from_date).format("D MMM")
} else {
return `${dayjs(props.doc.from_date).format("D MMM")} - ${dayjs(
props.doc.to_date
).format("D MMM")}`
}
})
const currency = computed(() => getCompanyCurrencySymbol(props.doc.company))
const approvalStatus = computed(() => {
return props.doc.approval_status === "Draft"
? "Pending"
: props.doc.approval_status
})
</script>
Loading

0 comments on commit 28c9216

Please sign in to comment.