diff --git a/web/package.json b/web/package.json
index 513b159..cee463b 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,5 +1,5 @@
{
- "version": "0.4.80",
+ "version": "0.4.81",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/web/src/core/photo.ts b/web/src/core/photo.ts
index c8c5268..382b66a 100644
--- a/web/src/core/photo.ts
+++ b/web/src/core/photo.ts
@@ -102,11 +102,51 @@ class Photo {
*/
public get takenAt(): string {
if (!this.metadata.takenAt) return '';
+
const takenAt = new Date(this.metadata.takenAt);
- return `${takenAt.getFullYear()}/${(takenAt.getMonth() + 1).toString().padStart(2, '0')}/${takenAt.getDate().toString().padStart(2, '0')} ${takenAt
- .getHours()
- .toString()
- .padStart(2, '0')}:${takenAt.getMinutes().toString().padStart(2, '0')}:${takenAt.getSeconds().toString().padStart(2, '0')}`;
+ switch (localStorage.getItem('dateNotation') || '2001/01/01 01:01:01') {
+ case '2001/01/01 01:01:01':
+ return `${takenAt.getFullYear()}/${(takenAt.getMonth() + 1).toString().padStart(2, '0')}/${takenAt.getDate().toString().padStart(2, '0')} ${takenAt
+ .getHours()
+ .toString()
+ .padStart(2, '0')}:${takenAt.getMinutes().toString().padStart(2, '0')}:${takenAt.getSeconds().toString().padStart(2, '0')}`;
+
+ case '2001-01-01 01:01:01':
+ return `${takenAt.getFullYear()}-${(takenAt.getMonth() + 1).toString().padStart(2, '0')}-${takenAt.getDate().toString().padStart(2, '0')} ${takenAt
+ .getHours()
+ .toString()
+ .padStart(2, '0')}:${takenAt.getMinutes().toString().padStart(2, '0')}:${takenAt.getSeconds().toString().padStart(2, '0')}`;
+
+ case '2001年01月01日 01時01分':
+ return `${takenAt.getFullYear()}年${(takenAt.getMonth() + 1).toString().padStart(2, '0')}月${takenAt.getDate().toString().padStart(2, '0')}日 ${takenAt
+ .getHours()
+ .toString()
+ .padStart(2, '0')}時${takenAt.getMinutes().toString().padStart(2, '0')}分`;
+
+ case '2001년 01월 01일 01시 01분':
+ return `${takenAt.getFullYear()}년 ${(takenAt.getMonth() + 1).toString().padStart(2, '0')}월 ${takenAt.getDate().toString().padStart(2, '0')}일 ${takenAt
+ .getHours()
+ .toString()
+ .padStart(2, '0')}시 ${takenAt.getMinutes().toString().padStart(2, '0')}분`;
+
+ case '2001/01/01':
+ return `${takenAt.getFullYear()}/${(takenAt.getMonth() + 1).toString().padStart(2, '0')}/${takenAt.getDate().toString().padStart(2, '0')}`;
+
+ case '2001-01-01':
+ return `${takenAt.getFullYear()}-${(takenAt.getMonth() + 1).toString().padStart(2, '0')}-${takenAt.getDate().toString().padStart(2, '0')}`;
+
+ case '2001年01月01日':
+ return `${takenAt.getFullYear()}年${(takenAt.getMonth() + 1).toString().padStart(2, '0')}月${takenAt.getDate().toString().padStart(2, '0')}日`;
+
+ case '2001년 01월 01일':
+ return `${takenAt.getFullYear()}년 ${(takenAt.getMonth() + 1).toString().padStart(2, '0')}월 ${takenAt.getDate().toString().padStart(2, '0')}일`;
+
+ case 'Jan 1, 2001':
+ return `${['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][takenAt.getMonth()]} ${takenAt.getDate().toString().padStart(2, '0')}, ${takenAt.getFullYear()}`;
+
+ default:
+ return '';
+ }
}
}
diff --git a/web/src/icons/time.icon.tsx b/web/src/icons/time.icon.tsx
new file mode 100644
index 0000000..4872cc7
--- /dev/null
+++ b/web/src/icons/time.icon.tsx
@@ -0,0 +1,12 @@
+import { Icon } from 'konsta/react';
+import { IoMdTime } from 'react-icons/io';
+
+interface TimeIconProps {
+ size?: number;
+}
+
+const TimeIcon = ({ size }: TimeIconProps) => {
+ return } />;
+};
+
+export default TimeIcon;
diff --git a/web/src/locales/translations/en.json b/web/src/locales/translations/en.json
index 9286dac..d5e8f89 100644
--- a/web/src/locales/translations/en.json
+++ b/web/src/locales/translations/en.json
@@ -58,6 +58,7 @@
"root.settings.export-to-jpeg": "Export to JPEG",
"root.settings.quality": "Quality",
"root.settings.fix-image-width": "Fix Image Width",
+ "root.settings.date-notation": "Date Notation",
"root.settings.focal-length-35mm-mode": "Focal Length 35mm Mode",
"root.settings.focal-length-ratio": "Crop Factor",
"root.settings.focal-length-ratio-mode": "Fixed Crop Factor",
@@ -79,5 +80,8 @@
"lab.description": "The experimental function may appear like the wind and disappear without a sound.",
"lab.collage": "Collage",
"lab.collage-description": "Create a collage with multiple photos.",
- "lab.collage-options": "You can set the top, bottom, left, and right margins and the space between photos."
+ "lab.collage-options": "You can set the top, bottom, left, and right margins and the space between photos.",
+
+ "fail-to-load-photos": "Failed to load photos.",
+ "please-check-your-photo-extension": "Please check your photo file extension."
}
diff --git a/web/src/locales/translations/ja.json b/web/src/locales/translations/ja.json
index c05eaf7..706dd72 100644
--- a/web/src/locales/translations/ja.json
+++ b/web/src/locales/translations/ja.json
@@ -58,6 +58,7 @@
"root.settings.export-to-jpeg": "JPEGにエクスポート",
"root.settings.quality": "画質",
"root.settings.fix-image-width": "画像幅を固定",
+ "root.settings.date-notation": "日付表記",
"root.settings.focal-length-35mm-mode": "35mm換算焦点距離",
"root.settings.focal-length-ratio": "焦点距離比率",
"root.settings.focal-length-ratio-mode": "焦点距離比率モード",
@@ -79,5 +80,8 @@
"lab.description": "実験室機能は風のように現れ、音もなく消えることがあります。",
"lab.collage": "コラージュ",
"lab.collage-description": "写真をコラージュします。",
- "lab.collage-options": "上下左右の余白と写真間の余白を設定できます。"
+ "lab.collage-options": "上下左右の余白と写真間の余白を設定できます。",
+
+ "fail-to-load-photos": "写真の読み込みに失敗しました。",
+ "please-check-your-photo-extension": "写真の拡張子を確認してください。"
}
diff --git a/web/src/locales/translations/ko.json b/web/src/locales/translations/ko.json
index 68a1e97..c5019ad 100644
--- a/web/src/locales/translations/ko.json
+++ b/web/src/locales/translations/ko.json
@@ -59,6 +59,7 @@
"root.settings.export-to-jpeg": "JPEG로 내보내기",
"root.settings.quality": "품질",
"root.settings.fix-image-width": "사진 너비 고정",
+ "root.settings.date-notation": "날짜 표기법",
"root.settings.focal-length-35mm-mode": "35mm 환산 화각 표시",
"root.settings.focal-length-ratio": "크롭 팩터",
"root.settings.focal-length-ratio-mode": "크롭 팩터 강제 변경",
@@ -80,5 +81,8 @@
"lab.description": "실험실 기능은 바람처럼 나타났다 소리없이 사라질 수 있습니다.",
"lab.collage": "콜라주",
"lab.collage-description": "여러 장의 사진을 한 장으로 합치는 기능입니다.",
- "lab.collage-options": "상하좌우 여백과 사진 간 여백을 설정할 수 있습니다."
+ "lab.collage-options": "상하좌우 여백과 사진 간 여백을 설정할 수 있습니다.",
+
+ "fail-to-load-photos": "사진을 불러오는데 실패했습니다",
+ "please-check-your-photo-extension": "사진 확장자를 확인해주세요"
}
diff --git a/web/src/pages/convert/components/add-photo-error.dialog.tsx b/web/src/pages/convert/components/add-photo-error.dialog.tsx
new file mode 100644
index 0000000..3c79770
--- /dev/null
+++ b/web/src/pages/convert/components/add-photo-error.dialog.tsx
@@ -0,0 +1,20 @@
+import { Dialog, DialogButton } from 'konsta/react';
+import { useStore } from '../../../store';
+import { useTranslation } from 'react-i18next';
+
+const AddPhotoErrorDialog = () => {
+ const { t } = useTranslation();
+ const { openedAddPhotoErrorDialog, setOpenedAddPhotoErrorDialog } = useStore();
+
+ return (
+