Skip to content

Commit

Permalink
Merge pull request #874 from NUTFes/develop
Browse files Browse the repository at this point in the history
9/3リリース
  • Loading branch information
Kubosaka authored Sep 3, 2024
2 parents dd64a07 + 3aca1dd commit 8631fd0
Show file tree
Hide file tree
Showing 21 changed files with 371 additions and 187 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FinanSu.iml
finansu.env
finansu.local.env
api/tmp
.DS_Store

# cloudflare
web/**/*.json
Expand Down
22 changes: 19 additions & 3 deletions view/next-project/src/components/common/EditButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { RiPencilFill } from 'react-icons/ri';
interface Props {
onClick?: () => void;
isDisabled?: boolean;
size?: 'S' | 'M' | 'L';
}

const EditButton: React.FC<Props> = (props) => {
const { onClick, isDisabled = false } = props;
const { onClick, isDisabled = false, size } = props;

const buttonClass = useMemo(() => {
if (isDisabled) {
Expand All @@ -17,17 +18,32 @@ const EditButton: React.FC<Props> = (props) => {
}
}, [isDisabled]);

const iconSize = (): { button: string; icon: string } => {
switch (size) {
case 'S':
return { button: '6', icon: '12' };
case 'M':
return { button: '12', icon: '20' };
case 'L':
return { button: '24', icon: '30' };
default:
return { button: '6', icon: '12' };
}
};

return (
<button
suppressHydrationWarning
className={`${buttonClass} flex h-6 w-6 min-w-0 items-center justify-center rounded-full p-0`}
className={`${buttonClass} flex h-${iconSize().button} w-${
iconSize().button
} min-w-0 items-center justify-center rounded-full p-0`}
disabled={isDisabled}
onClick={(e) => {
if (onClick) onClick();
e.stopPropagation();
}}
>
<RiPencilFill size={'15px'} color={'white'} />
<RiPencilFill size={`${iconSize().icon}px`} color={'white'} />
</button>
);
};
Expand Down
2 changes: 1 addition & 1 deletion view/next-project/src/components/common/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface Props {

function Input(props: Props): JSX.Element {
const className =
'rounded-full border border-primary-1 py-2 px-4' +
'rounded-full border border-primary-1 py-2 px-4 w-full' +
(props.className ? ` ${props.className}` : '');
return (
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import router from 'next/router';
import { useEffect, useState } from 'react';
import { Expense, PurchaseOrder, PurchaseReport } from '@/type/common';
import { useState } from 'react';
import { Expense, PurchaseOrder, PurchaseReportView } from '@/type/common';
import { put } from '@/utils/api/purchaseOrder';
import { get } from '@api/api_methods';
import {
CloseButton,
Input,
Expand All @@ -14,38 +13,13 @@ import {

export const DetailEditModal: React.FC<{
purchaseReportId: number;
purchaseReportViewItem: PurchaseReportView;
expenses: Expense[];
isOpen: boolean;
setIsOpen: () => void;
onOpenInitial: () => void;
}> = ({ purchaseReportId, setIsOpen, onOpenInitial }) => {
const [expenses, setExpenses] = useState<Expense[]>([]);
const [purchaseOrder, setPurchaseOrder] = useState<PurchaseOrder>({
id: 0,
deadline: '',
userID: 0,
expenseID: 0,
financeCheck: false,
});

useEffect(() => {
const fetchData = async () => {
try {
const purchaseReportRes: PurchaseReport = await get(
`${process.env.CSR_API_URI}/purchasereports/${purchaseReportId}`,
);
const purchaseOrderId = purchaseReportRes.purchaseOrderID;
const expensesRes: Expense[] = await get(`${process.env.CSR_API_URI}/expenses`);
const purchaseOrderRes: PurchaseOrder = await get(
`${process.env.CSR_API_URI}/purchaseorders/${purchaseOrderId}`,
);
setExpenses(expensesRes);
setPurchaseOrder(purchaseOrderRes);
} catch (error) {
console.error('Failed to fetch data:', error);
}
};
fetchData();
}, [purchaseReportId]);
}> = ({ purchaseReportViewItem, expenses, setIsOpen, onOpenInitial }) => {
const [formData, setFormData] = useState<PurchaseOrder>(purchaseReportViewItem.purchaseOrder);

const formatDate = (date: string) => {
const d = new Date(date);
Expand All @@ -57,15 +31,15 @@ export const DetailEditModal: React.FC<{

const submit = async () => {
try {
const updatePurchaseOrderUrl = `${process.env.CSR_API_URI}/purchaseorders/${purchaseOrder.id}`;
await put(updatePurchaseOrderUrl, purchaseOrder);
const updatePurchaseOrderUrl = `${process.env.CSR_API_URI}/purchaseorders/${formData.id}`;
await put(updatePurchaseOrderUrl, formData);
} finally {
router.reload();
}
};

const handleInputChange = (key: keyof PurchaseOrder, value: string | number) => {
setPurchaseOrder((prev) => ({ ...prev, [key]: value }));
setFormData((prev) => ({ ...prev, [key]: value }));
};

return (
Expand All @@ -80,7 +54,7 @@ export const DetailEditModal: React.FC<{
<p className='text-lg text-black-600'>購入した局</p>
<div className='col-span-3 w-full'>
<Select
value={purchaseOrder.expenseID}
value={formData.expenseID}
onChange={(e) => handleInputChange('expenseID', Number(e.target.value))}
>
{expenses.map((data) => (
Expand All @@ -95,7 +69,7 @@ export const DetailEditModal: React.FC<{
<div className='col-span-3 w-full'>
<Input
type='date'
value={purchaseOrder.deadline ? formatDate(purchaseOrder.deadline) : ''}
value={formData.deadline ? formatDate(formData.deadline) : ''}
onChange={(e) => handleInputChange('deadline', e.target.value)}
className='w-full'
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import * as React from 'react';
import { useState } from 'react';

import { DetailEditModal } from './DetailEditModal';
import { Expense, PurchaseReportView } from '@/type/common';
import { CloseButton, EditButton, Modal, PrimaryButton } from '@components/common';
import EditModal from '@components/purchasereports/EditModal';

interface Props {
children?: React.ReactNode;
purchaseReportViewItem: PurchaseReportView;
expenses: Expense[];
id: number;
isDisabled: boolean;
}
Expand Down Expand Up @@ -47,6 +50,8 @@ const OpenEditModalButton: React.FC<Props> = (props) => {
{step === 'editDetails' && (
<DetailEditModal
purchaseReportId={props.id}
expenses={props.expenses}
purchaseReportViewItem={props.purchaseReportViewItem}
isOpen={true}
setIsOpen={closeModal}
onOpenInitial={onOpenInitial}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ const UplaodFileModal: FC<ModalProps> = (props) => {
});
};

const generateRandomString = (charCount = 7): string => {
const str = Math.random().toString(36).substring(2).slice(-charCount);
return str.length < charCount ? str + 'a'.repeat(charCount - str.length) : str;
};

const submit = async () => {
if (!imageFile) {
return;
Expand All @@ -65,9 +70,24 @@ const UplaodFileModal: FC<ModalProps> = (props) => {

setIsLoading(true);
const formData = new FormData();

//拡張子取得
const uploadFileName = imageFile?.name || '';
const Extension = uploadFileName.split('.').pop();

// 日付取得
const date = new Date();
const thisMonth = date.getMonth() + 1;
const month = thisMonth < 10 ? '0' + thisMonth : thisMonth;
const day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
const formattedDate = `${date.getFullYear()}${month}${day}`;
const randomStr = generateRandomString();

// ファイル名作成
const fileName = `receipt_${formattedDate}_${randomStr}.${Extension}`;

formData.append('file', imageFile);
const fileName = imageFile?.name || '';
formData.append('fileName', `receipts/${fileName}`);
formData.append('fileName', fileName);
formData.append('year', year);

const response = await fetch('/api/receipts', {
Expand All @@ -94,7 +114,7 @@ const UplaodFileModal: FC<ModalProps> = (props) => {
const sendReceipt: Receipt = {
purchaseReportID: Number(id),
bucketName: process.env.NEXT_PUBLIC_BUCKET_NAME || '',
fileName: imageFile.name,
fileName: fileName,
fileType: imageFile.type,
remark: '',
};
Expand Down Expand Up @@ -176,7 +196,7 @@ const UplaodFileModal: FC<ModalProps> = (props) => {
</div>
</div>
<div className='my-2 flex w-full flex-wrap justify-center'>
<PrimaryButton type='button' onClick={() => submit()} disabled={isLoading && !imageFile}>
<PrimaryButton type='button' onClick={() => submit()} disabled={isLoading || !imageFile}>
登録
</PrimaryButton>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import React, { useState } from 'react';

import { OpenEditInvoiceModalButton } from './index';
import { createSponsorActivitiesPDF } from '@/utils/createSponsorActivitiesInvoicesPDF';
import { PreviewPDF } from '@/utils/createSponsorActivitiesInvoicesPDF';
import { CloseButton, Input, Modal, PrimaryButton } from '@components/common';
import { SponsorActivityView } from '@type/common';
import {
SponsorActivityView,
Invoice,
SponsorStyleDetail,
InvoiceSponsorStyle,
} from '@type/common';

interface ModalProps {
setIsOpen: (isOpen: boolean) => void;
Expand All @@ -17,6 +23,7 @@ interface FormDateFormat {
}

export default function AddPdfDetailModal(props: ModalProps) {
const { sponsorActivitiesViewItem } = props;
const today = new Date();
const yyyy = String(today.getFullYear());
const mm = '08';
Expand Down Expand Up @@ -47,80 +54,100 @@ export default function AddPdfDetailModal(props: ModalProps) {
).padStart(2, '0')}`;
};

const [formData, setFormData] = useState<FormDateFormat>({
receivedAt: ymd,
billIssuedAt: todayFormatted(),
const sponsorStyleFormatted = (): InvoiceSponsorStyle[] => {
return sponsorActivitiesViewItem.styleDetail.map((sponsorStyleDetail) => {
const sponsorStyle = sponsorStyleDetail.sponsorStyle;
const res: InvoiceSponsorStyle = {
styleName: `${sponsorStyle.style}(${sponsorStyle.feature})`,
price: sponsorStyle.price,
};
return res;
});
};

const CalculateTotalPrice = () => {
return sponsorActivitiesViewItem.styleDetail.reduce(
(price: number, sponsorStyleDetail: SponsorStyleDetail): number => {
return price + sponsorStyleDetail.sponsorStyle.price;
},
0,
);
};

const [invoiceData, setInvoiceDate] = useState<Invoice>({
sponsorName: sponsorActivitiesViewItem.sponsor.name,
managerName: sponsorActivitiesViewItem.sponsor.representative,
totalPrice: CalculateTotalPrice(),
fesStuffName: sponsorActivitiesViewItem.user.name,
invoiceSponsorStyle: sponsorStyleFormatted(),
issuedDate: todayFormatted(),
deadline: ymd,
remark: '',
});
const [remarks, setRemarks] = useState('');

const handler =
(input: string) =>
(e: React.ChangeEvent<HTMLSelectElement> | React.ChangeEvent<HTMLInputElement>) => {
setFormData({ ...formData, [input]: e.target.value });
setInvoiceDate({ ...invoiceData, [input]: e.target.value });
};

const handleRemarksChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRemarks(e.target.value);
const onClose = () => {
props.setIsOpen(false);
};

return (
<Modal className='md:w-1/2'>
<Modal className='md:w-1/2' onClick={onClose}>
<div className='w-full'>
<div className='ml-auto w-fit'>
<CloseButton
onClick={() => {
props.setIsOpen(false);
}}
/>
<CloseButton onClick={onClose} />
</div>
<p className='mx-auto mb-7 w-fit text-2xl font-thin leading-8 tracking-widest text-black-600'>
振込締め切り日・備考の入力
請求書の発行
</p>
<div className='col-span-4 w-full'>
<p className='text-gray-600 mb-3 ml-1 text-sm'>請求書発行日</p>
<Input
type='date'
value={formData.billIssuedAt}
onChange={handler('billIssuedAt')}
value={invoiceData.issuedDate}
onChange={handler('issuedDate')}
className='mb-3 w-full'
/>
<p className='text-gray-600 mb-3 ml-1 text-sm'>振込締め切り日</p>
<Input
type='date'
value={formData.receivedAt}
onChange={handler('receivedAt')}
value={invoiceData.deadline}
onChange={handler('deadline')}
className='mb-3 w-full'
/>
<p className='text-gray-600 mb-3 ml-1 text-sm'>備考を入力</p>
<Input
type='text'
value={remarks}
onChange={handleRemarksChange}
value={invoiceData.remark}
onChange={handler('remark')}
className='mb-3 w-full'
/>
</div>
<div className='mb-3 flex w-full justify-center'>
<div className='mb-3 flex w-full justify-center gap-4'>
<PrimaryButton
onClick={async () => {
createSponsorActivitiesPDF(
props.sponsorActivitiesViewItem,
formatDate(formData.receivedAt),
formatDate(formData.billIssuedAt, false),
remarks,
invoiceData,
formatDate(invoiceData.deadline),
formatDate(invoiceData.issuedDate, false),
);
props.setIsOpen(false);
onClose();
}}
>
ダウンロード
</PrimaryButton>
<OpenEditInvoiceModalButton invoice={invoiceData} setInvoice={setInvoiceDate} />
</div>
</div>
<div className='h-[30rem] justify-center overflow-x-auto md:flex'>
<PreviewPDF
sponsorActivitiesViewItem={props.sponsorActivitiesViewItem}
date={formatDate(formData.receivedAt)}
issuedDate={formatDate(formData.billIssuedAt, false)}
remarks={remarks}
invoiceItem={invoiceData}
deadline={formatDate(invoiceData.deadline)}
issuedDate={formatDate(invoiceData.issuedDate, false)}
/>
</div>
</Modal>
Expand Down
Loading

0 comments on commit 8631fd0

Please sign in to comment.