feat(migrations): add README for node-pg-migrate and enhance frontend configuration
- Created a README file for database migrations using node-pg-migrate, detailing commands, file format, best practices, and an example migration. - Added a Vite configuration file for the frontend, including plugin setup, alias resolution, build optimizations, and responsive design adjustments for task list components. - Updated i18n configuration to preload the 'home' namespace for improved localization. - Enhanced task list styling with responsive design features for better mobile usability.
This commit is contained in:
@@ -10,6 +10,7 @@ i18n
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
defaultNS: 'common',
|
||||
ns: ['common', 'home'], // Preload home namespace
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
|
||||
@@ -6,3 +6,81 @@
|
||||
.ant-table-row:hover .row-action-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Responsive styles for task list */
|
||||
@media (max-width: 768px) {
|
||||
.task-list-card .ant-card-head {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.task-list-card .ant-card-head-title {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.task-list-card .ant-card-extra {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.task-list-mobile-header {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: stretch !important;
|
||||
}
|
||||
|
||||
.task-list-mobile-controls {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: stretch !important;
|
||||
}
|
||||
|
||||
.task-list-mobile-select {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.task-list-mobile-segmented {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.task-list-card .ant-table {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.task-list-card .ant-table-thead > tr > th {
|
||||
padding: 8px 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.task-list-card .ant-table-tbody > tr > td {
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
.row-action-button {
|
||||
opacity: 1; /* Always show on mobile */
|
||||
}
|
||||
|
||||
/* Hide project column on very small screens */
|
||||
.task-list-card .ant-table-thead > tr > th:nth-child(2),
|
||||
.task-list-card .ant-table-tbody > tr > td:nth-child(2) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table responsive container */
|
||||
.task-list-card .ant-table-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.task-list-card .ant-table-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.task-list-card .ant-table {
|
||||
min-width: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
} from 'antd';
|
||||
import React, { useState, useMemo, useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useMediaQuery } from 'react-responsive';
|
||||
|
||||
import ListView from './list-view';
|
||||
import CalendarView from './calendar-view';
|
||||
@@ -61,21 +62,22 @@ const TasksList: React.FC = React.memo(() => {
|
||||
refetchOnFocus: false,
|
||||
});
|
||||
|
||||
const { t } = useTranslation('home');
|
||||
const { t, ready } = useTranslation('home');
|
||||
const { model } = useAppSelector(state => state.homePageReducer);
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 });
|
||||
|
||||
const taskModes = useMemo(
|
||||
() => [
|
||||
{
|
||||
value: 0,
|
||||
label: t('home:tasks.assignedToMe'),
|
||||
label: ready ? t('tasks.assignedToMe') : 'Assigned to me',
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: t('home:tasks.assignedByMe'),
|
||||
label: ready ? t('tasks.assignedByMe') : 'Assigned by me',
|
||||
},
|
||||
],
|
||||
[t]
|
||||
[t, ready]
|
||||
);
|
||||
|
||||
const handleSegmentChange = (value: 'List' | 'Calendar') => {
|
||||
@@ -123,7 +125,7 @@ const TasksList: React.FC = React.memo(() => {
|
||||
<span>{t('tasks.name')}</span>
|
||||
</Flex>
|
||||
),
|
||||
width: '40%',
|
||||
width: isMobile ? '50%' : '40%',
|
||||
render: (_, record) => (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Tooltip title={record.name}>
|
||||
@@ -155,7 +157,7 @@ const TasksList: React.FC = React.memo(() => {
|
||||
{
|
||||
key: 'project',
|
||||
title: t('tasks.project'),
|
||||
width: '25%',
|
||||
width: isMobile ? '30%' : '25%',
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Tooltip title={record.project_name}>
|
||||
@@ -185,7 +187,7 @@ const TasksList: React.FC = React.memo(() => {
|
||||
render: (_, record) => <HomeTasksDatePicker record={record} />,
|
||||
},
|
||||
],
|
||||
[t, data?.body?.total, currentPage, pageSize, handlePageChange]
|
||||
[t, data?.body?.total, currentPage, pageSize, handlePageChange, isMobile]
|
||||
);
|
||||
|
||||
const handleTaskModeChange = (value: number) => {
|
||||
@@ -210,23 +212,27 @@ const TasksList: React.FC = React.memo(() => {
|
||||
);
|
||||
}, [dispatch]);
|
||||
|
||||
|
||||
return (
|
||||
<Card
|
||||
className="task-list-card"
|
||||
title={
|
||||
<Flex gap={8} align="center">
|
||||
<Flex gap={8} align="center" className="task-list-mobile-header">
|
||||
<Typography.Title level={5} style={{ margin: 0 }}>
|
||||
{t('tasks.tasks')}
|
||||
</Typography.Title>
|
||||
<Select
|
||||
defaultValue={taskModes[0].label}
|
||||
value={homeTasksConfig.tasks_group_by || 0}
|
||||
options={taskModes}
|
||||
onChange={value => handleTaskModeChange(+value)}
|
||||
fieldNames={{ label: 'label', value: 'value' }}
|
||||
className="task-list-mobile-select"
|
||||
style={{ minWidth: 160 }}
|
||||
/>
|
||||
</Flex>
|
||||
}
|
||||
extra={
|
||||
<Flex gap={8} align="center">
|
||||
<Flex gap={8} align="center" className="task-list-mobile-controls">
|
||||
<Tooltip title={t('tasks.refresh')} trigger={'hover'}>
|
||||
<Button
|
||||
shape="circle"
|
||||
@@ -241,6 +247,7 @@ const TasksList: React.FC = React.memo(() => {
|
||||
]}
|
||||
defaultValue="List"
|
||||
onChange={handleSegmentChange}
|
||||
className="task-list-mobile-segmented"
|
||||
/>
|
||||
</Flex>
|
||||
}
|
||||
@@ -283,6 +290,7 @@ const TasksList: React.FC = React.memo(() => {
|
||||
rowClassName={() => 'custom-row-height'}
|
||||
loading={homeTasksFetching && skipAutoRefetch}
|
||||
pagination={false}
|
||||
scroll={{ x: 'max-content' }}
|
||||
/>
|
||||
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user