Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sell的基礎介面 #126

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.6",
"postcss": "^8.4.45",
"tailwindcss": "^3.4.10",
"tailwindcss": "^3.4.14",
"typescript": "^5.2.2",
"vite": "^5.2.10",
"vite-plugin-pwa": "^0.20.0",
Expand Down
25 changes: 25 additions & 0 deletions src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Route as MapIndexImport } from './routes/map/index'
import { Route as EventsIndexImport } from './routes/events/index'
import { Route as DinnerIndexImport } from './routes/dinner/index'
import { Route as CalendarIndexImport } from './routes/calendar/index'
import { Route as SalesAddsellImport } from './routes/sales/add_sell'
import { Route as HomeInfoCardImport } from './routes/home/infoCard'
import { Route as EventsCreateImport } from './routes/events/create'
import { Route as EventsEventIdImport } from './routes/events/$eventId'
Expand Down Expand Up @@ -66,6 +67,11 @@ const CalendarIndexRoute = CalendarIndexImport.update({
getParentRoute: () => rootRoute,
} as any)

const SalesAddsellRoute = SalesAddsellImport.update({
path: '/sales/add_sell',
getParentRoute: () => rootRoute,
} as any)

const HomeInfoCardRoute = HomeInfoCardImport.update({
id: '/home/infoCard',
path: '/home/infoCard',
Expand Down Expand Up @@ -123,6 +129,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof HomeInfoCardImport
parentRoute: typeof rootRoute
}
'/sales/add_sell': {
id: '/sales/add_sell'
path: '/sales/add_sell'
fullPath: '/sales/add_sell'
preLoaderRoute: typeof SalesAddsellImport
parentRoute: typeof rootRoute
}
'/calendar/': {
id: '/calendar/'
path: '/calendar'
Expand Down Expand Up @@ -169,6 +182,7 @@ export interface FileRoutesByFullPath {
'/events/$eventId': typeof EventsEventIdRoute
'/events/create': typeof EventsCreateRoute
'/home/infoCard': typeof HomeInfoCardRoute
'/sales/add_sell': typeof SalesAddsellRoute
'/calendar': typeof CalendarIndexRoute
'/dinner': typeof DinnerIndexRoute
'/events': typeof EventsIndexRoute
Expand All @@ -182,6 +196,7 @@ export interface FileRoutesByTo {
'/events/$eventId': typeof EventsEventIdRoute
'/events/create': typeof EventsCreateRoute
'/home/infoCard': typeof HomeInfoCardRoute
'/sales/add_sell': typeof SalesAddsellRoute
'/calendar': typeof CalendarIndexRoute
'/dinner': typeof DinnerIndexRoute
'/events': typeof EventsIndexRoute
Expand All @@ -196,6 +211,7 @@ export interface FileRoutesById {
'/events/$eventId': typeof EventsEventIdRoute
'/events/create': typeof EventsCreateRoute
'/home/infoCard': typeof HomeInfoCardRoute
'/sales/add_sell': typeof SalesAddsellRoute
'/calendar/': typeof CalendarIndexRoute
'/dinner/': typeof DinnerIndexRoute
'/events/': typeof EventsIndexRoute
Expand All @@ -211,6 +227,7 @@ export interface FileRouteTypes {
| '/events/$eventId'
| '/events/create'
| '/home/infoCard'
| '/sales/add_sell'
| '/calendar'
| '/dinner'
| '/events'
Expand All @@ -223,6 +240,7 @@ export interface FileRouteTypes {
| '/events/$eventId'
| '/events/create'
| '/home/infoCard'
| '/sales/add_sell'
| '/calendar'
| '/dinner'
| '/events'
Expand All @@ -235,6 +253,7 @@ export interface FileRouteTypes {
| '/events/$eventId'
| '/events/create'
| '/home/infoCard'
| '/sales/add_sell'
| '/calendar/'
| '/dinner/'
| '/events/'
Expand All @@ -249,6 +268,7 @@ export interface RootRouteChildren {
EventsEventIdRoute: typeof EventsEventIdRoute
EventsCreateRoute: typeof EventsCreateRoute
HomeInfoCardRoute: typeof HomeInfoCardRoute
SalesAddsellRoute: typeof SalesAddsellRoute
CalendarIndexRoute: typeof CalendarIndexRoute
DinnerIndexRoute: typeof DinnerIndexRoute
EventsIndexRoute: typeof EventsIndexRoute
Expand All @@ -262,6 +282,7 @@ const rootRouteChildren: RootRouteChildren = {
EventsEventIdRoute: EventsEventIdRoute,
EventsCreateRoute: EventsCreateRoute,
HomeInfoCardRoute: HomeInfoCardRoute,
SalesAddsellRoute: SalesAddsellRoute,
CalendarIndexRoute: CalendarIndexRoute,
DinnerIndexRoute: DinnerIndexRoute,
EventsIndexRoute: EventsIndexRoute,
Expand All @@ -284,6 +305,7 @@ export const routeTree = rootRoute
"/events/$eventId",
"/events/create",
"/home/infoCard",
"/sales/add_sell",
"/calendar/",
"/dinner/",
"/events/",
Expand All @@ -306,6 +328,9 @@ export const routeTree = rootRoute
"/home/infoCard": {
"filePath": "home/infoCard.tsx"
},
"/sales/add_sell": {
"filePath": "sales/add_sell.tsx"
},
"/calendar/": {
"filePath": "calendar/index.tsx"
},
Expand Down
128 changes: 128 additions & 0 deletions src/routes/sales/add_sell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { createFileRoute } from '@tanstack/react-router';
import { Header } from '../../components';
import { BasicIcon } from '../../components/icons/BasicIcon';
import { AuthGuard } from '../../utils/auth';
import { supabase } from '../../utils/supabase';

const styles = {
container: {
flex: 1,
backgroundColor: '#333',
},
daviddaytw marked this conversation as resolved.
Show resolved Hide resolved
searchSection: {
display: 'flex',
alignItems: 'center',
padding: 4,
backgroundColor: '#333',
},
searchInput: {
flex: 1,
marginLeft: 8,
marginRight: 8,
backgroundColor: '#f0f0f0',
borderRadius: 5,
padding: 4,
},
categories: {
display: 'inline',
padding: 5,
},
categoryButton: {
paddingLeft: 8,
paddingRight: 8,
margin: 2,
backgroundColor: '#888',
borderRadius: 12,
color: 'black',
},
grid: {
padding: '10px',
display: 'flex',
flexWrap: 'wrap',
gap: '10px',
justifyContent: 'space-between',
},
card: {
flex: '1 1 calc(25% - 10px)',
maxWidth: 'calc(25% - 10px)',
marginBottom: '10px',
padding: '10px',
backgroundColor: '#555',
borderRadius: '10px',
color: 'white',
boxSizing: 'border-box',
},
productName: {
fontSize: 16,
color: 'white',
},
productInfo: {
fontSize: 14,
color: 'gray',
},
icon: {
alignSelf: 'flex-end',
},
fab: {
position: 'absolute',
bottom: 20,
right: 20,
backgroundColor: '#6200ee',
width: 60,
height: 60,
borderRadius: 30,
justifyContent: 'center',
alignItems: 'center',
},
};

export const Route = createFileRoute('/sales/add_sell')({
beforeLoad: AuthGuard,
loader: async () => {
const { data, error } = await supabase
.from('sales')
.select('*')
if (error !== null) {
throw error
}

return { sales: data }
},
Comment on lines +81 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Implement pagination and improve error handling

The current data fetching implementation has several potential issues:

  • Fetching all sales records at once could impact performance
  • Generic error handling might not be user-friendly

Consider implementing pagination and better error handling:

loader: async () => {
+ const PAGE_SIZE = 20;
  const { data, error } = await supabase
    .from('sales')
    .select('*')
+   .range(0, PAGE_SIZE - 1)
+   .order('created_at', { ascending: false })
  if (error !== null) {
-   throw error
+   throw new Error(`Failed to fetch sales: ${error.message}`)
  }

- return { sales: data }
+ return { 
+   sales: data,
+   hasMore: data.length === PAGE_SIZE
+ }
}

Committable suggestion skipped: line range outside the PR's diff.

component: EventSale
})
function EventSale() {
const { sales } = Route.useLoaderData()
return (
<>
<Header />
<div style={styles.container}>
<div style={styles.searchSection}>
<BasicIcon size={24}>
<circle cx="12" cy="12" r="14" />
</BasicIcon>
<input style={styles.searchInput} placeholder="搜尋" />
<BasicIcon size={24}>
<circle cx="12" cy="12" r="14" />
</BasicIcon>
</div>
<div style={styles.categories}>
<button style={styles.categoryButton}>全部</button>
<button style={styles.categoryButton}>五金</button>
<button style={styles.categoryButton}>飲料</button>
<button style={styles.categoryButton}>贈品</button>
</div>
<div style={styles.grid}>
{
sales.map((p) => (
<div key={p.id} style={styles.card}>
<h1 style={styles.productName}>{p.product}</h1>
<p style={styles.productInfo}>價格: {p.price} 元</p>
</div>
))
}
Comment on lines +115 to +122
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add loading and error states

The sales data rendering doesn't handle loading or error states, which could lead to poor user experience.

Add proper state handling:

function EventSale() {
  const { sales } = Route.useLoaderData()
+ const [isLoading, setIsLoading] = useState(true)

+ if (isLoading) {
+   return <div>Loading sales data...</div>
+ }

+ if (!sales?.length) {
+   return <div>No sales data available</div>
+ }

  return (
    // ... existing JSX
  )
}

Committable suggestion skipped: line range outside the PR's diff.

</div>
</div>
</>
)
}
Comment on lines +93 to +127
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Implement search functionality and add TypeScript types

The component has several areas for improvement:

  • Search input is non-functional
  • Category buttons are hardcoded without filtering logic
  • Missing TypeScript type definitions

Consider implementing these improvements:

interface Sale {
  id: string;
  product: string;
  price: number;
  category: string;
}

function EventSale() {
  const { sales } = Route.useLoaderData()
  const [searchTerm, setSearchTerm] = useState('')
  const [selectedCategory, setSelectedCategory] = useState('all')

  const filteredSales = sales.filter((sale: Sale) => {
    const matchesSearch = sale.product.toLowerCase().includes(searchTerm.toLowerCase())
    const matchesCategory = selectedCategory === 'all' || sale.category === selectedCategory
    return matchesSearch && matchesCategory
  })

  return (
    // ... existing JSX with updated handlers
    <input 
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      style={styles.searchInput} 
      placeholder="搜尋" 
    />
    // ... rest of the component
  )
}


Loading