Skip to content

Commit

Permalink
Merge pull request #157 from kimthu09/mai
Browse files Browse the repository at this point in the history
update: db, dashboard skeleton loading
  • Loading branch information
kimthu09 authored Jan 16, 2024
2 parents b378b25 + 9a7eebf commit cdbf12b
Show file tree
Hide file tree
Showing 13 changed files with 452 additions and 257 deletions.
5 changes: 5 additions & 0 deletions backend/common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,8 @@ const DefaultPass = "app123"
const CurrentUserStr = "current_user"

const MinuteVerifyEmail = 15

const (
DefaultImageBook string = "https://firebasestorage.googleapis.com/v0/b/coffee-shop-web.appspot.com/o/Default%2Fbook.jpg?alt=media"
DefaultImageAvatar string = "https://firebasestorage.googleapis.com/v0/b/coffee-shop-web.appspot.com/o/Default%2Favatar.jpg?alt=media"
)
25 changes: 23 additions & 2 deletions backend/common/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,16 @@ func ValidateEmail(s string) bool {
return err == nil
}

func ValidateUrl(s string) bool {
u, err := url.ParseRequestURI(s)
func ValidateUrl(s *string, defaultValue string) bool {
if s == nil {
s = &defaultValue
return true
}
if *s == "" {
*s = defaultValue
return true
}
u, err := url.ParseRequestURI(*s)

if err != nil || u.Scheme == "" {
return false
Expand All @@ -42,6 +50,19 @@ func ValidateUrl(s string) bool {
return true
}

func ValidateImage(s *string, defaultValue string) bool {
if s == nil {
s = &defaultValue
return true
}
if *s == "" {
*s = defaultValue
return true
}

return true
}

func ValidateNotNilId(id *string) bool {
if id == nil || len(*id) == 0 || len(*id) > MaxLengthIdCanGenerate {
return false
Expand Down
6 changes: 5 additions & 1 deletion backend/module/book/bookmodel/err.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ var (
"Giá bán không hợp lệ",
"ErrBookSellPriceInvalid",
)

ErrBookImageInvalid = common.NewCustomError(
errors.New("image of book is invalid"),
"Ảnh của sách không hợp lệ",
"ErrBookImageInvalid",
)
ErrBookIdDuplicate = common.ErrDuplicateKey(
errors.New("Sách đã tồn tại"),
)
Expand Down
3 changes: 3 additions & 0 deletions backend/module/book/bookmodel/req_create_book.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@ func (b *ReqCreateBook) Validate() error {
if b.SellPrice == nil || !common.ValidatePositiveNumber(*b.SellPrice) {
return ErrBookSellPriceInvalid
}
if b.Image != nil || !common.ValidateImage(b.Image, common.DefaultImageBook) {
return ErrBookImageInvalid
}
return nil
}
3 changes: 3 additions & 0 deletions backend/module/book/bookmodel/req_update_book.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,8 @@ func (b *ReqUpdateBook) Validate() error {
if b.SellPrice != nil && !common.ValidatePositiveNumber(*b.SellPrice) {
return ErrBookSellPriceInvalid
}
if b.Image != nil || !common.ValidateImage(b.Image, common.DefaultImageBook) {
return ErrBookImageInvalid
}
return nil
}
2 changes: 1 addition & 1 deletion backend/module/user/usermodel/req_create_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (data *ReqCreateUser) Validate() error {
if !common.ValidateNotNilId(&data.RoleId) {
return ErrUserRoleInvalid
}
if !common.ValidateUrl(data.ImgUrl) {
if !common.ValidateImage(&data.ImgUrl, common.DefaultImageAvatar) {
return ErrUserImageInvalid
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion backend/module/user/usermodel/req_update_info_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (data *ReqUpdateInfoUser) Validate() error {
if data.Phone != nil && len(*data.Phone) != 0 && !common.ValidatePhone(*data.Phone) {
return ErrUserPhoneInvalid
}
if data.ImgUrl != nil && !common.ValidateUrl(*data.ImgUrl) {
if data.ImgUrl != nil && !common.ValidateImage(data.ImgUrl, common.DefaultImageAvatar) {
return ErrUserImageInvalid
}
return nil
Expand Down
6 changes: 5 additions & 1 deletion frontend/components/dashboard/dashboard-card-container.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DashboardCard from "./dashboard-card";

const DashboardCardHolder = (props: any) => {
const { cardInfos } = props;
const { isLoading, cardInfos } = props;
return (
<div className="flex lg:flex-row flex-col gap-4">
<div className="flex flex-row gap-4 flex-1">
Expand All @@ -10,12 +10,14 @@ const DashboardCardHolder = (props: any) => {
icon={cardInfos[0].icon}
value={cardInfos[0].value}
color="bg-[rgba(207,250,218,0.5)] text-[#2f6e3f]"
isLoading={isLoading}
/>
<DashboardCard
title={cardInfos[1].title}
icon={cardInfos[1].icon}
value={cardInfos[1].value}
color="bg-[rgba(177,240,252,0.5)] text-[#0a6273]"
isLoading={isLoading}
/>
</div>
<div className="flex flex-row lg:gap-[6] gap-4 flex-1">
Expand All @@ -24,12 +26,14 @@ const DashboardCardHolder = (props: any) => {
icon={cardInfos[2].icon}
value={cardInfos[2].value}
color="bg-[rgba(247,231,161,0.5)] text-[#876a03]"
isLoading={isLoading}
/>
<DashboardCard
title={cardInfos[3].title}
icon={cardInfos[3].icon}
value={cardInfos[3].value}
color="bg-[rgba(209,214,255,0.5)] text-[#081687]"
isLoading={isLoading}
/>
</div>
</div>
Expand Down
21 changes: 15 additions & 6 deletions frontend/components/dashboard/dashboard-card.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import { Card } from "../ui/card";
import { Skeleton } from "../ui/skeleton";

const DashboardCard = (props: any) => {
const { title, icon, value, color } = props;
const { title, icon, value, color, isLoading } = props;

return (
<Card
className={`flex flex-col lg:gap-4 p-8 gap-2 flex-1 ${
color ? color : ""
}`}
>
<div className="flex flex-row gap-2 items-center">
<p className="text-lg">{title}</p>
{icon}
</div>
<p className="text-2xl font-semibold">{value}</p>
{isLoading ? (
<Skeleton className="h-6 w-16" />
) : (
<div className="flex flex-row gap-2 items-center">
<p className="text-lg">{title}</p>
{icon}
</div>
)}
{isLoading ? (
<Skeleton className="h-6 w-20" />
) : (
<p className="text-2xl font-semibold">{value}</p>
)}
</Card>
);
};
Expand Down
129 changes: 74 additions & 55 deletions frontend/components/dashboard/dashboard-chart-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { Check, ChevronsUpDown } from "lucide-react";

import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Command,
CommandGroup,
CommandItem,
} from "@/components/ui/command";
import { Command, CommandGroup, CommandItem } from "@/components/ui/command";
import {
Popover,
PopoverContent,
Expand All @@ -18,67 +14,90 @@ import {
import DashboardChart from "./dashboard-chart";
import { Card } from "../ui/card";
import { typeCharts } from "@/constants";
import { Skeleton } from "../ui/skeleton";


const DashboardChartContainer = (props: any) => {
const { price, profit, timeFrom, timeTo, chartType, setChartType } = props;
const {
price,
profit,
timeFrom,
timeTo,
chartType,
setChartType,
isLoading,
} = props;
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState(chartType);

return (
<Card className="p-4 flex-[2] w-full flex flex-col gap-4">
<div className="flex flex-row gap-4">
<div className="flex-1"></div>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? typeCharts.find((type) => type.value === value)?.label
: "Chọn loại biểu đồ"}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandGroup>
{typeCharts.map((type) => (
<CommandItem
key={type.value}
value={type.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue);
setOpen(false);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
value === type.value ? "opacity-100" : "opacity-0"
)}
/>
{type.label}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
<Button onClick={() => setChartType(value)} className="px-5">
Xem
</Button>
{isLoading ? (
<Skeleton className="h-8 w-32" />
) : (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[200px] justify-between"
>
{value
? typeCharts.find((type) => type.value === value)?.label
: "Chọn loại biểu đồ"}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandGroup>
{typeCharts.map((type) => (
<CommandItem
key={type.value}
value={type.value}
onSelect={(currentValue) => {
setValue(currentValue === value ? "" : currentValue);
setOpen(false);
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
value === type.value ? "opacity-100" : "opacity-0"
)}
/>
{type.label}
</CommandItem>
))}
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
)}

{isLoading ? (
<Skeleton className="h-8 w-16" />
) : (
<Button onClick={() => setChartType(value)} className="px-5">
Xem
</Button>
)}
</div>
<div className="flex-1 overflow-x-auto min-w-full max-w-[20vw] min-h-[28rem]">
<DashboardChart
type={chartType}
price={price}
profit={profit}
timeFrom={timeFrom}
timeTo={timeTo}
/>
{isLoading ? (
<Skeleton className="w-full aspect-square"/>
) : (
<DashboardChart
type={chartType}
price={price}
profit={profit}
timeFrom={timeFrom}
timeTo={timeTo}
/>
)}
</div>
</Card>
);
Expand Down
31 changes: 29 additions & 2 deletions frontend/components/dashboard/dashboard-top-food-container.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
import TableSkeleton from "../skeleton/table-skeleton";
import { Card } from "../ui/card";
import { DashboardTopFoodTable } from "./dashboard-top-food-table";

const DashboardTopFoodContainer = (props: any) => {
const { foods } = props;
const { foods, isLoading } = props;
return (
<Card className="flex flex-col flex-1 w-full h-full gap-2 p-4">
<p className="font-semibold text-base">Sản phẩm bán chạy</p>
<DashboardTopFoodTable data={foods} />
{isLoading ? (
<TableSkeleton
isHasExtensionAction={false}
isHasFilter={false}
isHasSearch={false}
isHasChooseVisibleRow={false}
isHasCheckBox={false}
isHasPaging={false}
numberRow={5}
cells={[
{
percent: 1
},
{
percent: 5
},
{
percent: 2
},
{
percent: 2
}
]}
/>
) : (
<DashboardTopFoodTable data={foods} />
)}
</Card>
);
};
Expand Down
Loading

0 comments on commit cdbf12b

Please sign in to comment.