Skip to content

Commit

Permalink
Merge pull request #140 from UTDallasEPICS/FamilyReportsRevamp
Browse files Browse the repository at this point in the history
Family reports revamp
  • Loading branch information
pariahGH authored Mar 7, 2024
2 parents f1a11ac + 48e3d08 commit 4eec79c
Show file tree
Hide file tree
Showing 46 changed files with 838 additions and 487 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ node_modules
.nitro
.cache
.output
.env
*env*
!.env.example
dist
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@ Need Private keys for
- Stripe
- AWS
- Auth0
- Constant Contacts
Need
- email source for AWS SES
- S3 bucket URL
- Auth0 Issuer URL

Install the dependencies:

Ideally use npm
```bash
# yarn
yarn install

# npm
npm install
npm install

# yarn
yarn install

# pnpm
pnpm install --shamefully-hoist
Expand Down
1 change: 1 addition & 0 deletions components/CVDatepicker.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template lang="pug">
Datepicker.rounded-md.p-2(type="String" v-model="value")
slot
</template>

<script setup lang="ts">
Expand Down
22 changes: 13 additions & 9 deletions components/CVHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import type { User, Page } from "@/types.d.ts"
import { donationFormat, dateFormat } from '@/utils'
const cvuser = useCookie<User>('cvuser');
const cvtoken = useCookie('cvtoken');
const isAdmin = computed(() => cvuser.value?.user_role == "advocate" || cvuser.value?.user_role == "admin")
const isAdvocateAdmin = computed(() => cvuser.value?.user_role == "admin" || cvuser.value?.user_role == "advocate")
const isAdmin = computed(() => cvuser.value?.user_role == "admin")
const cuid = computed(() => cvuser.value?.cuid)
const familyCuid = computed(() => cvuser.value?.familyCuid)
const isLoggedIn = computed(() => cvuser.value)
const pages = ref<Page[]>([])
const searchQuery = ref('');
const route = useRoute()
const isNotSearch = computed(() => route.path !== "/Search/")
console.log(route.path)
</script>

<template lang="pug">
Expand All @@ -23,23 +24,23 @@ ClientOnly
href="/api/logout"
)
p.uppercase.white.w-max LOGOUT
NavLinkButton(:to="`/PageList/${cuid}/?fromUsers=0`" v-if="isAdmin")
NavLinkButton(:to="`/PageList/${cuid}/?fromUsers=0`" v-if="isAdvocateAdmin")
p.uppercase.white.w-max Pages
NavLinkButton(:to="`/pageList/${familyCuid}/?fromUsers=0`" v-if="!isAdmin")
NavLinkButton(:to="`/pageList/${familyCuid}/?fromUsers=0`" v-if="!isAdvocateAdmin")
p.uppercase.white.w-max Pages
NavLinkButton(to='/EditPage/0')
p.uppercase.white.w-max New page
NavLinkButton( v-if="isAdmin" to='/Users')
NavLinkButton( v-if="isAdvocateAdmin" to='/Users')
p.uppercase.white.w-max Users
NavLinkButton( v-if="isAdmin" to='/EditUser/0')
NavLinkButton( v-if="isAdvocateAdmin" to='/EditUser/0')
p.uppercase.white.w-max Invite user
NavLinkButton( v-if="isAdmin" to='/EditFamily')
NavLinkButton( v-if="isAdvocateAdmin" to='/EditFamily')
p.uppercase.white.w-max Create Family
NavLinkButton(to="/")
p.uppercase.white.w-max Home
NavLinkButton(v-if="isAdmin" to='/FamilyTransactionList')
p.uppercase.white.w-max Donations
NavLinkButton(v-if="isAdmin" to='/FamilyReports')
NavLinkButton(v-if="isAdvocateAdmin" to='/FamilyReports')
p.uppercase.white.w-max Family Reports
div.max-w-min.mx-auto.flex.gap-2(v-else)
a.items-center.px-2.py-2.text-base.font-medium.rounded-md.text-green-600.cursor-pointer(style="border: 1px solid #c4c4c4;"
Expand All @@ -56,10 +57,13 @@ ClientOnly
NavLinkButton(to='https://carsonsvillage.org/' target="_blank")
p.uppercase.white.w-max ABOUT US

//&& isLoggedIn")
.flex.w-max(v-if="isNotSearch")
input(class="border border-gray-300 py-2 px-4 rounded-lg focus:outline-none focus:border-black-500" type="search" placeholder=" " v-model="searchQuery")
NuxtLink.inline(:to="`/Search/?search=${searchQuery}`")
NuxtLink.inline(:to="`/Search/?search=${searchQuery}&isPageList=0`")
img(src="/CVSearchIcon.png")
//.flex.w-max(v-else) Todo: add to search page
p.uppercase.white.w-max Welcome TO Carson's Village
</template>

<style scoped></style>
24 changes: 22 additions & 2 deletions components/CVProgress.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
<script lang="ts" setup>
const props = defineProps<{modelBarWidth: string}>()
const actualBarWidth = computed(() => { if(props.modelBarWidth != null && props.modelBarWidth !="inf" ) {
if(parseFloat(props.modelBarWidth) >= 100) {
return 100
} else if(parseFloat(props.modelBarWidth) < 100 && parseFloat(props.modelBarWidth) > 0) {
return parseFloat(props.modelBarWidth)
} else {
return 0
}
} else if(props.modelBarWidth == "inf") {
return 100
}})
console.log(parseFloat(props.modelBarWidth), " bar width")
// handles logic with how to display the progress bar
function calculateBarWidth (modelBarWidth: string) {
console.log(modelBarWidth)
}
console.log(actualBarWidth.value)
const style = computed(() =>
`background: linear-gradient(90deg, rgba(15,200,0,1), rgba(133,233,0,1) 35%); box-shadow: 0 3px 3px -5px #1ba710, 0 2px 5px #1ba710; width:${props.modelBarWidth}%`);
`background: linear-gradient(90deg, rgba(15,200,0,1), rgba(133,233,0,1) 35%); box-shadow: 0 3px 3px -5px #1ba710, 0 2px 5px #1ba710; width:${actualBarWidth.value}%`);
</script>

<template lang="pug">
.rounded-full.text-white.flex.items-center.justify-center(:style="style")
slot
slot(v-if="actualBarWidth")
</template>

<style scoped></style>
3 changes: 3 additions & 0 deletions components/CVReplySystem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ const replyData = ref<Partial<Reply>>({
const clearSuccessMessage = () => {
successMessage.value = '';
//replyData.value.name = ""; // Clear name field
//replyData.value.reply = ""; // Clear reply field
}
const successMessage = ref("");
// todo: change to $fetch
const submitComment = async () => {
const response = await useFetch('/api/replies', { // look at nuxt documentation for $fetch
method: 'POST',
Expand Down
11 changes: 8 additions & 3 deletions components/DonationEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,26 @@ const donationData = ref<PageDonation>({
cuid: "",
pageCuid: props.pageCuid,
familyCuid: props.familyCuid,
transaction_id : "",
transaction_id: "",
donorFirstName: "",
donorLastName: "",
comments: "",
isAnonymous : false
comments: "",
Page: ref<Page[]>([]).value[0],
userCuid: '',
isAnonymous: false
});
const stripeLink_ref = ref("")
const create_checkout_session = async () => {
// todo: depreciate
const donorData = {
first_name: donationData.value.donorFirstName,
last_name: donationData.value.donorLastName,
isAnonymous: donationData.value.isAnonymous,
comments: donationData.value.comments
};
// todo: change to $fetch
const { data : sessionInfo } = await useFetch('/api/create_session', {
method: 'POST',
body: { ...donationData.value, cuid: props.pageCuid, family_cuid: props.familyCuid, amount_raised: Math.trunc(parseFloat(donationData.value.amount as unknown as string) * 100) as number}
Expand Down
12 changes: 6 additions & 6 deletions components/ImageUpload.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { Image } from '../types.d.ts';
// TODO: this component needs to handle getting the presigned url (which should also create an Image entry in the database), performing the upload, and then emitting the Image object (not the file) so that
// This component handles getting the presigned url (which should also create an Image entry in the database), performing the upload, and then emitting the Image object (not the file) so that
// the parent component can add it to its list
// when saving a page, we ignore the images array
// page editor can select from currently uploaded images to pick the cuid of the one to use as profile image
Expand All @@ -13,18 +13,18 @@ type imageLinkTypes = {
image: Image
}
const props = defineProps({
});
// actually uploads images using presigned url to s3 bucket
const props = defineProps<{pageCuid: string}>()
console.log(props.pageCuid)
// uploads images using presigned url to S3 bucket
const onFile = async (event: Event) => {
const Files = event?.target?.files
for(let i = 0 ; i < Files.length; i++){
const file = Files[i];
// Creates the presigned url and enters the image into the database
// todo: change to $fetch
const { data: imageData } = await useFetch('/api/image_upload', {
method: 'POST',
body: { contentLength: file.size, contentType: file.type, file }
body: { contentLength: file.size, contentType: file.type, file, pageCuid: ref(props.pageCuid) }
});
const { uploadUrl, image} = imageData.value as unknown as imageLinkTypes;
Expand Down
3 changes: 2 additions & 1 deletion components/PayoutRecord.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const cvuser = useCookie<User>('cvuser')
// Method that records donation payouts and increases the amount distributed for each page.
const save = async () => {
const{data: result } = await useFetch('/api/family_transaction_payout', {
// todo: change to $fetch // could improve preformance for Jason by significant amount
const{ data: result } = await useFetch('/api/family_transaction_payout', {
method: 'POST',
body: {
transaction_id: transaction_id.value,
Expand Down
35 changes: 24 additions & 11 deletions components/StandardTable.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts" setup>
import { dateFormat } from 'utils';
const props2 = defineProps<{ headers: [] }>()
const props = defineProps({
headers: {
Expand All @@ -13,25 +15,36 @@ const props = defineProps({
// tr(v-for="(header in headers)" :key="i")
// th.css {{ header.name }}
// tr(v-for="(header in headers)" :key="j")
// th.css {{ header.name }}
// LinkButton(v-if="header.isLink")
// LinkButton(v-if="${header.kind=="link"}" :to=header.property)
// td.css(v-else-if="${header.kind=="money"}") {{ donationFormat(header.property) }}
// td.css(v-else-if="${header.kind=="date"}") {{ dateFormat(header.property) }}
// td.css(v-else) {{ header.property }}
//
const rows = [
{
name: "row 1",
amount_raised: "5"
}
]
const headers = [
{
title: "Name",
name: "Name",
property: "name"
},
{
title: "Amount Raised",
property: "amount_raised"
name: "Amount Raised",
property: 2000,
kind: "money"
},
{
name: "",
property: "/Page/12sdfgsfdscadasd",
kind: "link"
},
{
name: "page name",
property: "Leorem Ipsum",
kind: "string"
},
{
name: "current date",
property: new Date().toString(),
kind: "date"
}
]
Expand Down
13 changes: 7 additions & 6 deletions components/imagePreview.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script lang="ts" setup>
import type { Image } from '@/types.d.ts'
const props = defineProps<{ images: Image[], profileImage: Image }>()
const props = defineProps<{ images: Image[], profileImage: Image, pageCuid: string }>()
const emit = defineEmits(["images","update:images","profileImage"])
console.log(props.pageCuid)
const previewCuid = ref("")
onMounted(() => {
previewCuid.value = props.images[0]?.cuid || ""
Expand All @@ -29,20 +29,21 @@ const emptyImage = ref<Image>({
})
// Method to remove a single image
const removeImage = async (cuid:string, isPreview: boolean) => {
const removeImage = async (cuid: string, isPreview: boolean) => {
if(cuid == previewCuid.value){
isPreview = true;
}
// Confirmation of image deletetion. If no is pressed nothing happens
if(confirm('Are you sure you want to delete this image?')){
const theImage = props.images.find((i:Image)=> i.cuid == cuid)
// todo: change to $fetch
await useFetch('/api/image', {
method: 'delete',
body: (theImage as Image)
});
let imagesTemp = props.images.filter((i:Image) => i.cuid != cuid)
emit("images", props.images.filter((i:Image) => i.cuid != cuid));
let imagesTemp = props.images.filter((i: Image) => i.cuid != cuid) //todo: replace emit on "images" with this?
emit("images", props.images.filter((i: Image) => i.cuid != cuid));
if(isPreview && imagesTemp.length !=0){
previewCuid.value = imagesTemp[0].cuid
} else if(imagesTemp.length === 0){
Expand Down Expand Up @@ -76,7 +77,7 @@ const saveImage = async (theImage: Image) => {
.absolute(style='top: 10px; right: 150px')
button.bg-red-500(class='w-40 sm:64' style="align-items: center;justify-content: center; line-height: 1;text-align: center; color: white; font-weight: 450; positon: absolute; top:0px; left: 0px; width: 30px; height: 2rem; border-radius: 50%; padding-bottom: 4px;" @click = "removeImage(previewCuid, true)") x
a.ml-10.pt-1(style="text-shadow: 3px 3px 4px rgba(0, 0, 0, 0.25);") image upload
ImageUpload(@imageUploaded="saveImage")
ImageUpload(@imageUploaded="saveImage" :pageCuid="props.pageCuid")
.py-4.grid.flex-box.flex-row.item-centered.gap-1(v-if="images.length!= 0" class="sm:grid-cols-3" style="line-height: 0px;text-align: center")
div(style="width:1200px" class="")
div(class="flex" style="overflow-x: auto")
Expand Down
Binary file not shown.
Loading

0 comments on commit 4eec79c

Please sign in to comment.